diff options
author | Alessio Treglia <alessio@debian.org> | 2011-08-27 10:54:22 +0200 |
---|---|---|
committer | Alessio Treglia <alessio@debian.org> | 2011-08-27 10:54:22 +0200 |
commit | 575d802c4f1a81ebce3b7b71be6dd3a51fddf7bd (patch) | |
tree | f67206af06039627d241d77bc83009505189b7eb | |
parent | 77a9b5bea4c6dc6977e51b002d92d268e57208f3 (diff) | |
parent | 87ebc2af1f0417b3bc38a233e28ff673eff4fa51 (diff) |
Merge commit 'upstream/3.1.5'
57 files changed, 27176 insertions, 9824 deletions
diff --git a/Makefile.in b/Makefile.in index 34f567e..9174b48 100644 --- a/Makefile.in +++ b/Makefile.in @@ -33,8 +33,9 @@ PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS COPYING \ - ChangeLog INSTALL NEWS depcomp install-sh missing + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ + compile depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -42,6 +43,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_GEN = $(am__v_GEN_$(V)) @@ -114,6 +116,8 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +COLORD_CFLAGS = @COLORD_CFLAGS@ +COLORD_LIBS = @COLORD_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -128,11 +132,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ HELP_DIR = @HELP_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -172,6 +176,7 @@ SIMPLE_SCAN_CFLAGS = @SIMPLE_SCAN_CFLAGS@ SIMPLE_SCAN_LIBS = @SIMPLE_SCAN_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ +VALAC = @VALAC@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -193,6 +198,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ @@ -234,7 +240,8 @@ DISTCLEANFILES = \ omf.make \ xmldocs.make -all: all-recursive +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: @@ -272,6 +279,23 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, @@ -352,7 +376,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) mkid -fID $$unique tags: TAGS -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ @@ -369,7 +393,7 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ @@ -387,9 +411,9 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ fi; \ fi ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ @@ -584,7 +608,7 @@ distcleancheck: distclean exit 1; } >&2 check-am: all-am check: check-recursive -all-am: Makefile +all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive @@ -620,7 +644,7 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive @@ -682,21 +706,21 @@ ps-am: uninstall-am: -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ - install-am install-strip tags-recursive +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ - distclean distclean-generic distclean-tags distcleancheck \ - distdir distuninstallcheck dvi dvi-am html html-am info \ - info-am install install-am install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs installdirs-am maintainer-clean \ + distclean distclean-generic distclean-hdr distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am @@ -1,3 +1,15 @@ +Overview of changes in simple-scan 3.1.5 + + * Fix compile warnings + +Overview of changes in simple-scan 3.1.3 + + * Port to Vala + * Port to GTK3 + * Port to GDBus + * Port to GSettings + * Port to colord + Overview of changes in simple-scan 2.32.0.2 * Add binary comment as recommended in PDF spec @@ -13,63 +13,20 @@ m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],, -[m4_warning([this file was generated for autoconf 2.67. +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, +[m4_warning([this file was generated for autoconf 2.68. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) -dnl AM_GCONF_SOURCE_2 -dnl Defines GCONF_SCHEMA_CONFIG_SOURCE which is where you should install schemas -dnl (i.e. pass to gconftool-2 -dnl Defines GCONF_SCHEMA_FILE_DIR which is a filesystem directory where -dnl you should install foo.schemas files -dnl - -AC_DEFUN([AM_GCONF_SOURCE_2], -[ - if test "x$GCONF_SCHEMA_INSTALL_SOURCE" = "x"; then - GCONF_SCHEMA_CONFIG_SOURCE=`gconftool-2 --get-default-source` - else - GCONF_SCHEMA_CONFIG_SOURCE=$GCONF_SCHEMA_INSTALL_SOURCE - fi - - AC_ARG_WITH([gconf-source], - AC_HELP_STRING([--with-gconf-source=sourceaddress], - [Config database for installing schema files.]), - [GCONF_SCHEMA_CONFIG_SOURCE="$withval"],) - - AC_SUBST(GCONF_SCHEMA_CONFIG_SOURCE) - AC_MSG_RESULT([Using config source $GCONF_SCHEMA_CONFIG_SOURCE for schema installation]) - - if test "x$GCONF_SCHEMA_FILE_DIR" = "x"; then - GCONF_SCHEMA_FILE_DIR='$(sysconfdir)/gconf/schemas' - fi - - AC_ARG_WITH([gconf-schema-file-dir], - AC_HELP_STRING([--with-gconf-schema-file-dir=dir], - [Directory for installing schema files.]), - [GCONF_SCHEMA_FILE_DIR="$withval"],) - - AC_SUBST(GCONF_SCHEMA_FILE_DIR) - AC_MSG_RESULT([Using $GCONF_SCHEMA_FILE_DIR as install directory for schema files]) - - AC_ARG_ENABLE(schemas-install, - AC_HELP_STRING([--disable-schemas-install], - [Disable the schemas installation]), - [case ${enableval} in - yes|no) ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-schemas-install]) ;; - esac]) - AM_CONDITIONAL([GCONF_SCHEMAS_INSTALL], [test "$enable_schemas_install" != no]) -]) - # gnome-common.m4 +# +# serial 3 # dnl GNOME_COMMON_INIT -AC_DEFUN([GNOME_COMMON_INIT], +AU_DEFUN([GNOME_COMMON_INIT], [ dnl this macro should come after AC_CONFIG_MACRO_DIR AC_BEFORE([AC_CONFIG_MACRO_DIR], [$0]) @@ -82,7 +39,10 @@ AC_DEFUN([GNOME_COMMON_INIT], fi AC_SUBST([ACLOCAL_AMFLAGS]) -]) +], +[[$0: This macro is deprecated. You should set put "ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}" +in your top-level Makefile.am, instead, where "m4" is the macro directory set +with AC_CONFIG_MACRO_DIR() in your configure.ac]]) AC_DEFUN([GNOME_DEBUG_CHECK], [ @@ -314,6 +274,90 @@ fi GNOME_DOC_DEFINES ]) +dnl GLIB_GSETTINGS +dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether +dnl the schema should be compiled +dnl + +AC_DEFUN([GLIB_GSETTINGS], +[ + m4_pattern_allow([AM_V_GEN]) + AC_ARG_ENABLE(schemas-compile, + AS_HELP_STRING([--disable-schemas-compile], + [Disable regeneration of gschemas.compiled on install]), + [case ${enableval} in + yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE="" ;; + no) GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-schemas-compile]) ;; + esac]) + AC_SUBST([GSETTINGS_DISABLE_SCHEMAS_COMPILE]) + PKG_PROG_PKG_CONFIG([0.16]) + AC_SUBST(gsettingsschemadir, [${datadir}/glib-2.0/schemas]) + if test x$cross_compiling != xyes; then + GLIB_COMPILE_SCHEMAS=`$PKG_CONFIG --variable glib_compile_schemas gio-2.0` + else + AC_PATH_PROG(GLIB_COMPILE_SCHEMAS, glib-compile-schemas) + fi + AC_SUBST(GLIB_COMPILE_SCHEMAS) + if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then + ifelse([$2],,[AC_MSG_ERROR([glib-compile-schemas not found.])],[$2]) + else + ifelse([$1],,[:],[$1]) + fi + + GSETTINGS_RULES=' +.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas + +mostlyclean-am: clean-gsettings-schemas + +gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE)) + +%.gschema.valid: %.gschema.xml $(gsettings__enum_file) + $(AM_V_GEN) if test -f "$<"; then d=; else d="$(srcdir)/"; fi; $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix --schema-file=,$(gsettings__enum_file)) --schema-file=$${d}$< && touch [$]@ + +all-am: $(gsettings_SCHEMAS:.xml=.valid) +uninstall-am: uninstall-gsettings-schemas +install-data-am: install-gsettings-schemas + +.SECONDARY: $(gsettings_SCHEMAS) + +install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file) + @$(NORMAL_INSTALL) + if test -n "$^"; then \ + test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \ + $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \ + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \ + fi + +uninstall-gsettings-schemas: + @$(NORMAL_UNINSTALL) + @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n "$(gsettingsschemadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir) + +clean-gsettings-schemas: + rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file) + +ifdef gsettings_ENUM_NAMESPACE +$(gsettings__enum_file): $(gsettings_ENUM_FILES) + $(AM_V_GEN) glib-mkenums --comments '\''<!-- @comment@ -->'\'' --fhead "<schemalist>" --vhead " <@type@ id='\''$(gsettings_ENUM_NAMESPACE).@EnumName@'\''>" --vprod " <value nick='\''@valuenick@'\'' value='\''@valuenum@'\''/>" --vtail " </@type@>" --ftail "</schemalist>" [$]^ > [$]@.tmp && mv [$]@.tmp [$]@ +endif +' + _GSETTINGS_SUBST(GSETTINGS_RULES) +]) + +dnl _GSETTINGS_SUBST(VARIABLE) +dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +AC_DEFUN([_GSETTINGS_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) + dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) # serial 40 IT_PROG_INTLTOOL @@ -569,7 +613,8 @@ AC_DEFUN([AM_NLS], # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) @@ -615,7 +660,8 @@ m4_define([_PKG_CONFIG], pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried @@ -663,9 +709,9 @@ if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else - $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD @@ -788,29 +834,6 @@ AC_PREREQ([2.50])dnl am_aux_dir=`cd $ac_aux_dir && pwd` ]) - -# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# This was merged into AC_PROG_CC in Autoconf. - -AU_DEFUN([AM_PROG_CC_STDC], -[AC_PROG_CC -AC_DIAGNOSE([obsolete], [$0: - your code should no longer depend upon `am_cv_prog_cc_stdc', but upon - `ac_cv_prog_cc_stdc'. Remove this warning and the assignment when - you adjust the code. You can also remove the above call to - AC_PROG_CC if you already called it elsewhere.]) -am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc -]) -AU_DEFUN([fp_PROG_CC_STDC]) - # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 @@ -1109,6 +1132,18 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, @@ -1382,6 +1417,41 @@ AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 @@ -1719,3 +1789,33 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +# Autoconf support for the Vala compiler + +# Copyright (C) 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# Check whether the Vala compiler exists in `PATH'. If it is found, the +# variable VALAC is set. Optionally a minimum release number of the +# compiler can be requested. +# +# AM_PROG_VALAC([MINIMUM-VERSION]) +# -------------------------------- +AC_DEFUN([AM_PROG_VALAC], +[AC_PATH_PROG([VALAC], [valac], []) + AS_IF([test -z "$VALAC"], + [AC_MSG_WARN([No Vala compiler found. You will not be able to compile .vala source files.])], + [AS_IF([test -n "$1"], + [AC_MSG_CHECKING([$VALAC is at least version $1]) + am__vala_version=`$VALAC --version | sed 's/Vala *//'` + AS_VERSION_COMPARE([$1], ["$am__vala_version"], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([Vala $1 not found.])])])]) +]) + @@ -0,0 +1,143 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2009-10-06.20; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software +# Foundation, Inc. +# Written by Tom Tromey <tromey@cygnus.com>. +# +# 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, 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/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; +esac + +ofile= +cfile= +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..1f311ac --- /dev/null +++ b/config.h.in @@ -0,0 +1,67 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <jpeglib.h> header file. */ +#undef HAVE_JPEGLIB_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <sane/saneopts.h> header file. */ +#undef HAVE_SANE_SANEOPTS_H + +/* Define to 1 if you have the <sane/sane.h> header file. */ +#undef HAVE_SANE_SANE_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.68. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -89,6 +89,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -214,11 +215,18 @@ IFS=$as_save_IFS # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : @@ -525,6 +533,66 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" +as_awk_strverscmp=' + # Use only awk features that work with 7th edition Unix awk (1978). + # My, what an old awk you have, Mr. Solaris! + END { + while (length(v1) && length(v2)) { + # Set d1 to be the next thing to compare from v1, and likewise for d2. + # Normally this is a single character, but if v1 and v2 contain digits, + # compare them as integers and fractions as strverscmp does. + if (v1 ~ /^[0-9]/ && v2 ~ /^[0-9]/) { + # Split v1 and v2 into their leading digit string components d1 and d2, + # and advance v1 and v2 past the leading digit strings. + for (len1 = 1; substr(v1, len1 + 1) ~ /^[0-9]/; len1++) continue + for (len2 = 1; substr(v2, len2 + 1) ~ /^[0-9]/; len2++) continue + d1 = substr(v1, 1, len1); v1 = substr(v1, len1 + 1) + d2 = substr(v2, 1, len2); v2 = substr(v2, len2 + 1) + if (d1 ~ /^0/) { + if (d2 ~ /^0/) { + # Compare two fractions. + while (d1 ~ /^0/ && d2 ~ /^0/) { + d1 = substr(d1, 2); len1-- + d2 = substr(d2, 2); len2-- + } + if (len1 != len2 && ! (len1 && len2 && substr(d1, 1, 1) == substr(d2, 1, 1))) { + # The two components differ in length, and the common prefix + # contains only leading zeros. Consider the longer to be less. + d1 = -len1 + d2 = -len2 + } else { + # Otherwise, compare as strings. + d1 = "x" d1 + d2 = "x" d2 + } + } else { + # A fraction is less than an integer. + exit 1 + } + } else { + if (d2 ~ /^0/) { + # An integer is greater than a fraction. + exit 2 + } else { + # Compare two integers. + d1 += 0 + d2 += 0 + } + } + } else { + # The normal case, without worrying about digits. + d1 = substr(v1, 1, 1); v1 = substr(v1, 2) + d2 = substr(v2, 1, 1); v2 = substr(v2, 2) + } + if (d1 < d2) exit 1 + if (d1 > d2) exit 2 + } + # Beware Solaris /usr/xgp4/bin/awk (at least through Solaris 10), + # which mishandles some comparisons of empty strings to integers. + if (length(v2)) exit 1 + if (length(v1)) exit 2 + } +' test -n "$DJDIR" || exec 7<&0 </dev/null exec 6>&1 @@ -635,19 +703,24 @@ DOC_USER_FORMATS OMF_DIR HELP_DIR LN_S +HAVE_COLORD_FALSE +HAVE_COLORD_TRUE +COLORD_LIBS +COLORD_CFLAGS SIMPLE_SCAN_LIBS SIMPLE_SCAN_CFLAGS +WARN_CFLAGS +GSETTINGS_RULES +GLIB_COMPILE_SCHEMAS +gsettingsschemadir PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG -WARN_CFLAGS -GCONF_SCHEMAS_INSTALL_FALSE -GCONF_SCHEMAS_INSTALL_TRUE -GCONF_SCHEMA_FILE_DIR -GCONF_SCHEMA_CONFIG_SOURCE +GSETTINGS_DISABLE_SCHEMAS_COMPILE EGREP GREP CPP +VALAC am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE @@ -737,9 +810,7 @@ enable_option_checking enable_maintainer_mode enable_silent_rules enable_dependency_tracking -with_gconf_source -with_gconf_schema_file_dir -enable_schemas_install +enable_schemas_compile enable_compile_warnings enable_iso_c with_help_dir @@ -761,7 +832,9 @@ PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR SIMPLE_SCAN_CFLAGS -SIMPLE_SCAN_LIBS' +SIMPLE_SCAN_LIBS +COLORD_CFLAGS +COLORD_LIBS' # Initialize some variables set by options. @@ -1166,7 +1239,7 @@ Try \`$0 --help' for more information" $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1382,8 +1455,8 @@ Optional Features: --disable-silent-rules verbose build output (undo: `make V=0') --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors - --disable-schemas-install - Disable the schemas installation + --disable-schemas-compile + Disable regeneration of gschemas.compiled on install --enable-compile-warnings=[no/minimum/yes/maximum/error] Turn on compiler warnings --enable-iso-c Try to warn if code is not ISO C @@ -1393,10 +1466,6 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-gconf-source=sourceaddress - Config database for installing schema files. - --with-gconf-schema-file-dir=dir - Directory for installing schema files. --with-help-dir=DIR path to help docs --with-omf-dir=DIR path to OMF files --with-help-formats=FORMATS @@ -1420,6 +1489,9 @@ Some influential environment variables: C compiler flags for SIMPLE_SCAN, overriding pkg-config SIMPLE_SCAN_LIBS linker flags for SIMPLE_SCAN, overriding pkg-config + COLORD_CFLAGS + C compiler flags for COLORD, overriding pkg-config + COLORD_LIBS linker flags for COLORD, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1488,7 +1560,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation @@ -1534,7 +1606,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1580,7 +1652,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link @@ -1617,7 +1689,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp @@ -1659,7 +1731,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run @@ -1672,10 +1744,10 @@ fi ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval "test \"\${$3+set}\"" = set; then : + if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -1738,7 +1810,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -1747,7 +1819,7 @@ eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel @@ -1760,7 +1832,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1778,7 +1850,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile @@ -1790,7 +1862,7 @@ ac_fn_c_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1845,7 +1917,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF @@ -1853,7 +1925,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2111,7 +2183,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;} || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -2248,7 +2320,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : +if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -2335,11 +2407,11 @@ am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5 ;; + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5 ;; + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; esac # Do `set' in a subshell so we don't clobber the current shell's @@ -2425,7 +2497,7 @@ if test "$cross_compiling" != no; then set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then : +if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then @@ -2465,7 +2537,7 @@ if test -z "$ac_cv_prog_STRIP"; then set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then @@ -2518,7 +2590,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then - if test "${ac_cv_path_mkdir+set}" = set; then : + if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -2569,7 +2641,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then : +if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then @@ -2609,7 +2681,7 @@ done $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then : +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF @@ -2667,7 +2739,7 @@ fi # Define the identity of the package. PACKAGE=simple-scan - VERSION=2.32.0.2 + VERSION=3.1.5 cat >>confdefs.h <<_ACEOF @@ -2707,6 +2779,8 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' +ac_config_headers="$ac_config_headers config.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } @@ -2828,7 +2902,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2868,7 +2942,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2921,7 +2995,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2961,7 +3035,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -3020,7 +3094,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -3064,7 +3138,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -3119,7 +3193,7 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3234,7 +3308,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3277,7 +3351,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3336,7 +3410,7 @@ $as_echo "$ac_try_echo"; } >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -3347,7 +3421,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3388,7 +3462,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -3398,7 +3472,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3435,7 +3509,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -3513,7 +3587,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -3612,7 +3686,7 @@ depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : +if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then @@ -3738,7 +3812,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 $as_echo_n "checking for library containing strerror... " >&6; } -if test "${ac_cv_search_strerror+set}" = set; then : +if ${ac_cv_search_strerror+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -3772,11 +3846,11 @@ for ac_lib in '' cposix; do fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test "${ac_cv_search_strerror+set}" = set; then : + if ${ac_cv_search_strerror+:} false; then : break fi done -if test "${ac_cv_search_strerror+set}" = set; then : +if ${ac_cv_search_strerror+:} false; then : else ac_cv_search_strerror=no @@ -3792,6 +3866,74 @@ if test "$ac_res" != no; then : fi +# Extract the first word of "valac", so it can be a program name with args. +set dummy valac; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VALAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VALAC in + [\\/]* | ?:[\\/]*) + ac_cv_path_VALAC="$VALAC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_VALAC="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +VALAC=$ac_cv_path_VALAC +if test -n "$VALAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALAC" >&5 +$as_echo "$VALAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -z "$VALAC"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No Vala compiler found. You will not be able to compile .vala source files." >&5 +$as_echo "$as_me: WARNING: No Vala compiler found. You will not be able to compile .vala source files." >&2;} +else + if test -n "0.13.0"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking $VALAC is at least version 0.13.0" >&5 +$as_echo_n "checking $VALAC is at least version 0.13.0... " >&6; } + am__vala_version=`$VALAC --version | sed 's/Vala *//'` + as_arg_v1=0.13.0 +as_arg_v2="$am__vala_version" +awk "$as_awk_strverscmp" v1="$as_arg_v1" v2="$as_arg_v2" /dev/null +case $? in #( + 1) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + 0) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + 2) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Vala 0.13.0 not found." "$LINENO" 5 ;; #( + *) : + ;; +esac +fi +fi + if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } @@ -3801,7 +3943,7 @@ $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval "test \"\${ac_cv_prog_cc_${ac_cc}_c_o+set}\"" = set; then : +if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3903,675 +4045,20 @@ $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdarg.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - - -am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -4585,7 +4072,7 @@ if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded @@ -4701,7 +4188,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -4713,7 +4200,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then @@ -4776,7 +4263,7 @@ $as_echo "$ac_cv_path_GREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 @@ -4843,7 +4330,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -4955,55 +4442,237 @@ fi - if test "x$GCONF_SCHEMA_INSTALL_SOURCE" = "x"; then - GCONF_SCHEMA_CONFIG_SOURCE=`gconftool-2 --get-default-source` - else - GCONF_SCHEMA_CONFIG_SOURCE=$GCONF_SCHEMA_INSTALL_SOURCE - fi - -# Check whether --with-gconf-source was given. -if test "${with_gconf_source+set}" = set; then : - withval=$with_gconf_source; GCONF_SCHEMA_CONFIG_SOURCE="$withval" + # Check whether --enable-schemas-compile was given. +if test "${enable_schemas_compile+set}" = set; then : + enableval=$enable_schemas_compile; case ${enableval} in + yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE="" ;; + no) GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;; + *) as_fn_error $? "bad value ${enableval} for --enable-schemas-compile" "$LINENO" 5 ;; + esac fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using config source $GCONF_SCHEMA_CONFIG_SOURCE for schema installation" >&5 -$as_echo "Using config source $GCONF_SCHEMA_CONFIG_SOURCE for schema installation" >&6; } - if test "x$GCONF_SCHEMA_FILE_DIR" = "x"; then - GCONF_SCHEMA_FILE_DIR='$(sysconfdir)/gconf/schemas' - fi -# Check whether --with-gconf-schema-file-dir was given. -if test "${with_gconf_schema_file_dir+set}" = set; then : - withval=$with_gconf_schema_file_dir; GCONF_SCHEMA_FILE_DIR="$withval" + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $GCONF_SCHEMA_FILE_DIR as install directory for schema files" >&5 -$as_echo "Using $GCONF_SCHEMA_FILE_DIR as install directory for schema files" >&6; } + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi - # Check whether --enable-schemas-install was given. -if test "${enable_schemas_install+set}" = set; then : - enableval=$enable_schemas_install; case ${enableval} in - yes|no) ;; - *) as_fn_error $? "bad value ${enableval} for --enable-schemas-install" "$LINENO" 5 ;; - esac fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + gsettingsschemadir=${datadir}/glib-2.0/schemas - if test "$enable_schemas_install" != no; then - GCONF_SCHEMAS_INSTALL_TRUE= - GCONF_SCHEMAS_INSTALL_FALSE='#' + if test x$cross_compiling != xyes; then + GLIB_COMPILE_SCHEMAS=`$PKG_CONFIG --variable glib_compile_schemas gio-2.0` + else + # Extract the first word of "glib-compile-schemas", so it can be a program name with args. +set dummy glib-compile-schemas; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GLIB_COMPILE_SCHEMAS+:} false; then : + $as_echo_n "(cached) " >&6 else - GCONF_SCHEMAS_INSTALL_TRUE='#' - GCONF_SCHEMAS_INSTALL_FALSE= + case $GLIB_COMPILE_SCHEMAS in + [\\/]* | ?:[\\/]*) + ac_cv_path_GLIB_COMPILE_SCHEMAS="$GLIB_COMPILE_SCHEMAS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GLIB_COMPILE_SCHEMAS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GLIB_COMPILE_SCHEMAS=$ac_cv_path_GLIB_COMPILE_SCHEMAS +if test -n "$GLIB_COMPILE_SCHEMAS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_COMPILE_SCHEMAS" >&5 +$as_echo "$GLIB_COMPILE_SCHEMAS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi + + if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then + as_fn_error $? "glib-compile-schemas not found." "$LINENO" 5 + else + : + fi + + GSETTINGS_RULES=' +.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas + +mostlyclean-am: clean-gsettings-schemas + +gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE)) + +%.gschema.valid: %.gschema.xml $(gsettings__enum_file) + $(AM_V_GEN) if test -f "$<"; then d=; else d="$(srcdir)/"; fi; $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix --schema-file=,$(gsettings__enum_file)) --schema-file=$${d}$< && touch $@ + +all-am: $(gsettings_SCHEMAS:.xml=.valid) +uninstall-am: uninstall-gsettings-schemas +install-data-am: install-gsettings-schemas + +.SECONDARY: $(gsettings_SCHEMAS) + +install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file) + @$(NORMAL_INSTALL) + if test -n "$^"; then \ + test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \ + $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \ + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \ + fi + +uninstall-gsettings-schemas: + @$(NORMAL_UNINSTALL) + @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n "$(gsettingsschemadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir) + +clean-gsettings-schemas: + rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file) + +ifdef gsettings_ENUM_NAMESPACE +$(gsettings__enum_file): $(gsettings_ENUM_FILES) + $(AM_V_GEN) glib-mkenums --comments '\''<!-- @comment@ -->'\'' --fhead "<schemalist>" --vhead " <@type@ id='\''$(gsettings_ENUM_NAMESPACE).@EnumName@'\''>" --vprod " <value nick='\''@valuenick@'\'' value='\''@valuenum@'\''/>" --vtail " </@type@>" --ftail "</schemalist>" $^ > $@.tmp && mv $@.tmp $@ +endif +' + + + + + + @@ -5114,127 +4783,6 @@ $as_echo "$complCFLAGS" >&6; } -GTK_REQUIRED=2.18.0 - - - - - - - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_PKG_CONFIG+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG -if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_PKG_CONFIG"; then - ac_pt_PKG_CONFIG=$PKG_CONFIG - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_PKG_CONFIG" = x; then - PKG_CONFIG="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PKG_CONFIG=$ac_pt_PKG_CONFIG - fi -else - PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -fi - -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=0.9.0 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - PKG_CONFIG="" - fi -fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SIMPLE_SCAN" >&5 @@ -5245,44 +4793,36 @@ if test -n "$SIMPLE_SCAN_CFLAGS"; then elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" - gtk+-2.0 >= \$GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 \""; } >&5 ($PKG_CONFIG --exists --print-errors " - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SIMPLE_SCAN_CFLAGS=`$PKG_CONFIG --cflags " - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 " 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi @@ -5294,44 +4834,36 @@ if test -n "$SIMPLE_SCAN_LIBS"; then elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" - gtk+-2.0 >= \$GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 \""; } >&5 ($PKG_CONFIG --exists --print-errors " - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SIMPLE_SCAN_LIBS=`$PKG_CONFIG --libs " - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 " 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi @@ -5351,29 +4883,23 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - SIMPLE_SCAN_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors " - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + SIMPLE_SCAN_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs " + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 " 2>&1` else - SIMPLE_SCAN_PKG_ERRORS=`$PKG_CONFIG --print-errors " - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + SIMPLE_SCAN_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs " + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 " 2>&1` fi @@ -5381,15 +4907,12 @@ fi echo "$SIMPLE_SCAN_PKG_ERRORS" >&5 as_fn_error $? "Package requirements ( - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 ) were not met: @@ -5415,7 +4938,7 @@ and SIMPLE_SCAN_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else SIMPLE_SCAN_CFLAGS=$pkg_cv_SIMPLE_SCAN_CFLAGS SIMPLE_SCAN_LIBS=$pkg_cv_SIMPLE_SCAN_LIBS @@ -5424,6 +4947,102 @@ $as_echo "yes" >&6; } fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for COLORD" >&5 +$as_echo_n "checking for COLORD... " >&6; } + +if test -n "$COLORD_CFLAGS"; then + pkg_cv_COLORD_CFLAGS="$COLORD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" + colord +\""; } >&5 + ($PKG_CONFIG --exists --print-errors " + colord +") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COLORD_CFLAGS=`$PKG_CONFIG --cflags " + colord +" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$COLORD_LIBS"; then + pkg_cv_COLORD_LIBS="$COLORD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" + colord +\""; } >&5 + ($PKG_CONFIG --exists --print-errors " + colord +") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COLORD_LIBS=`$PKG_CONFIG --libs " + colord +" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + COLORD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs " + colord +" 2>&1` + else + COLORD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs " + colord +" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$COLORD_PKG_ERRORS" >&5 + + have_colord=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_colord=no +else + COLORD_CFLAGS=$pkg_cv_COLORD_CFLAGS + COLORD_LIBS=$pkg_cv_COLORD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_colord=yes +fi + if test $have_colord = yes; then + HAVE_COLORD_TRUE= + HAVE_COLORD_FALSE='#' +else + HAVE_COLORD_TRUE='#' + HAVE_COLORD_FALSE= +fi + + # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h @@ -5444,7 +5063,7 @@ done for ac_header in sane/sane.h do : ac_fn_c_check_header_mongrel "$LINENO" "sane/sane.h" "ac_cv_header_sane_sane_h" "$ac_includes_default" -if test "x$ac_cv_header_sane_sane_h" = x""yes; then : +if test "x$ac_cv_header_sane_sane_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SANE_SANE_H 1 _ACEOF @@ -5458,7 +5077,7 @@ done for ac_header in sane/saneopts.h do : ac_fn_c_check_header_mongrel "$LINENO" "sane/saneopts.h" "ac_cv_header_sane_saneopts_h" "$ac_includes_default" -if test "x$ac_cv_header_sane_saneopts_h" = x""yes; then : +if test "x$ac_cv_header_sane_saneopts_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SANE_SANEOPTS_H 1 _ACEOF @@ -5472,7 +5091,7 @@ done for ac_header in jpeglib.h do : ac_fn_c_check_header_mongrel "$LINENO" "jpeglib.h" "ac_cv_header_jpeglib_h" "$ac_includes_default" -if test "x$ac_cv_header_jpeglib_h" = x""yes; then : +if test "x$ac_cv_header_jpeglib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_JPEGLIB_H 1 _ACEOF @@ -5629,7 +5248,7 @@ fi set dummy intltool-update; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_INTLTOOL_UPDATE+set}" = set; then : +if ${ac_cv_path_INTLTOOL_UPDATE+:} false; then : $as_echo_n "(cached) " >&6 else case $INTLTOOL_UPDATE in @@ -5669,7 +5288,7 @@ fi set dummy intltool-merge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_INTLTOOL_MERGE+set}" = set; then : +if ${ac_cv_path_INTLTOOL_MERGE+:} false; then : $as_echo_n "(cached) " >&6 else case $INTLTOOL_MERGE in @@ -5709,7 +5328,7 @@ fi set dummy intltool-extract; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_INTLTOOL_EXTRACT+set}" = set; then : +if ${ac_cv_path_INTLTOOL_EXTRACT+:} false; then : $as_echo_n "(cached) " >&6 else case $INTLTOOL_EXTRACT in @@ -5870,7 +5489,7 @@ INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcar set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_XGETTEXT+set}" = set; then : +if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case $XGETTEXT in @@ -5910,7 +5529,7 @@ fi set dummy msgmerge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MSGMERGE+set}" = set; then : +if ${ac_cv_path_MSGMERGE+:} false; then : $as_echo_n "(cached) " >&6 else case $MSGMERGE in @@ -5950,7 +5569,7 @@ fi set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MSGFMT+set}" = set; then : +if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $MSGFMT in @@ -5990,7 +5609,7 @@ fi set dummy gmsgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_GMSGFMT+set}" = set; then : +if ${ac_cv_path_GMSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $GMSGFMT in @@ -6041,7 +5660,7 @@ fi set dummy perl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_INTLTOOL_PERL+set}" = set; then : +if ${ac_cv_path_INTLTOOL_PERL+:} false; then : $as_echo_n "(cached) " >&6 else case $INTLTOOL_PERL in @@ -6125,7 +5744,7 @@ else case $host in *-*-solaris*) ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" -if test "x$ac_cv_func_bind_textdomain_codeset" = x""yes; then : +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : DATADIRNAME=share else DATADIRNAME=lib @@ -6215,10 +5834,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && + if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} @@ -6230,43 +5860,7 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - +DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= @@ -6305,12 +5899,8 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${GCONF_SCHEMAS_INSTALL_TRUE}" && test -z "${GCONF_SCHEMAS_INSTALL_FALSE}"; then - as_fn_error $? "conditional \"GCONF_SCHEMAS_INSTALL\" was never defined. +if test -z "${HAVE_COLORD_TRUE}" && test -z "${HAVE_COLORD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_COLORD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SK_TRUE}" && test -z "${ENABLE_SK_FALSE}"; then @@ -6326,7 +5916,7 @@ fi -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -6427,6 +6017,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -6734,7 +6325,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -6751,11 +6342,15 @@ case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" +config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF @@ -6777,10 +6372,15 @@ Usage: $0 [OPTION]... [TAG]... --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE Configuration files: $config_files +Configuration headers: +$config_headers + Configuration commands: $config_commands @@ -6791,7 +6391,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. @@ -6847,7 +6447,18 @@ do esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) @@ -6908,6 +6519,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; @@ -6917,7 +6529,7 @@ do "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -6928,6 +6540,7 @@ done # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi @@ -6939,9 +6552,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -6949,12 +6563,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -6976,7 +6591,7 @@ else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -7004,7 +6619,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -7052,7 +6667,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -7084,7 +6699,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF @@ -7114,8 +6729,116 @@ fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. -eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do @@ -7124,7 +6847,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -7143,7 +6866,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -7152,7 +6875,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -7178,8 +6901,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -7315,25 +7038,83 @@ s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} diff --git a/configure.ac b/configure.ac index a8788a3..24afcd8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,17 +1,18 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(configure.ac) -AM_INIT_AUTOMAKE(simple-scan, 2.32.0.2) +AM_INIT_AUTOMAKE(simple-scan, 3.1.5) +AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE GNOME_MAINTAINER_MODE_DEFINES m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_ISC_POSIX -AC_PROG_CC_C_O -AM_PROG_CC_STDC +AM_PROG_VALAC([0.13.0]) +AM_PROG_CC_C_O AC_HEADER_STDC -AM_GCONF_SOURCE_2 +GLIB_GSETTINGS GNOME_COMPILE_WARNINGS(maximum) @@ -23,21 +24,21 @@ dnl Run-time dependencies: dnl * gnome-icon-theme dnl * xdg-utils (for xdg-email) -GTK_REQUIRED=2.18.0 - PKG_CHECK_MODULES(SIMPLE_SCAN, [ - gtk+-2.0 >= $GTK_REQUIRED - gconf-2.0 + gtk+-3.0 gmodule-export-2.0 gthread-2.0 zlib cairo gdk-pixbuf-2.0 - cairo-pdf - dbus-glib-1 gudev-1.0 ]) +PKG_CHECK_MODULES(COLORD, [ + colord +], have_colord=yes, have_colord=no) +AM_CONDITIONAL(HAVE_COLORD, test $have_colord = yes) + AC_CHECK_HEADERS([sane/sane.h],[],[AC_MSG_ERROR([SANE not found])]) AC_CHECK_HEADERS([sane/saneopts.h],[],[AC_MSG_ERROR([SANE not found])]) AC_CHECK_HEADERS([jpeglib.h],[],[AC_MSG_ERROR([libjpeg not found])]) diff --git a/data/Makefile.am b/data/Makefile.am index d406905..c99f807 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -8,16 +8,16 @@ utilities_in_files = simple-scan.desktop.in utilities_DATA = $(utilities_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ -schemadir = @GCONF_SCHEMA_FILE_DIR@ -schema_in_files = simple-scan.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) -@INTLTOOL_SCHEMAS_RULE@ +gsettings_SCHEMAS = org.gnome.SimpleScan.gschema.xml +@INTLTOOL_XML_NOMERGE_RULE@ +@GSETTINGS_RULES@ man1_MANS = simple-scan.1 -EXTRA_DIST = $(ui_DATA) $(utilities_in_files) $(schema_in_files) $(man1_MANS) +EXTRA_DIST = $(ui_DATA) $(utilities_in_files) org.gnome.SimpleScan.gschema.xml.in $(man1_MANS) DISTCLEANFILES = \ Makefile.in \ $(schema_DATA) \ - $(utilities_DATA) + $(utilities_DATA) \ + $(gsettings_SCHEMAS) diff --git a/data/Makefile.in b/data/Makefile.in index da951ec..7745f03 100644 --- a/data/Makefile.in +++ b/data/Makefile.in @@ -39,6 +39,7 @@ am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_GEN = $(am__v_GEN_$(V)) @@ -78,11 +79,11 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man1dir = $(mandir)/man1 -am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(schemadir)" \ - "$(DESTDIR)$(uidir)" "$(DESTDIR)$(utilitiesdir)" +am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(uidir)" \ + "$(DESTDIR)$(utilitiesdir)" NROFF = nroff MANS = $(man1_MANS) -DATA = $(schema_DATA) $(ui_DATA) $(utilities_DATA) +DATA = $(ui_DATA) $(utilities_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ @@ -128,6 +129,8 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +COLORD_CFLAGS = @COLORD_CFLAGS@ +COLORD_LIBS = @COLORD_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -142,11 +145,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ HELP_DIR = @HELP_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -186,6 +189,7 @@ SIMPLE_SCAN_CFLAGS = @SIMPLE_SCAN_CFLAGS@ SIMPLE_SCAN_LIBS = @SIMPLE_SCAN_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ +VALAC = @VALAC@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -207,6 +211,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ @@ -237,15 +242,14 @@ ui_DATA = simple-scan.ui utilitiesdir = $(datadir)/applications utilities_in_files = simple-scan.desktop.in utilities_DATA = $(utilities_in_files:.desktop.in=.desktop) -schemadir = @GCONF_SCHEMA_FILE_DIR@ -schema_in_files = simple-scan.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) +gsettings_SCHEMAS = org.gnome.SimpleScan.gschema.xml man1_MANS = simple-scan.1 -EXTRA_DIST = $(ui_DATA) $(utilities_in_files) $(schema_in_files) $(man1_MANS) +EXTRA_DIST = $(ui_DATA) $(utilities_in_files) org.gnome.SimpleScan.gschema.xml.in $(man1_MANS) DISTCLEANFILES = \ Makefile.in \ $(schema_DATA) \ - $(utilities_DATA) + $(utilities_DATA) \ + $(gsettings_SCHEMAS) all: all-recursive @@ -314,26 +318,6 @@ uninstall-man1: test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; } -install-schemaDATA: $(schema_DATA) - @$(NORMAL_INSTALL) - test -z "$(schemadir)" || $(MKDIR_P) "$(DESTDIR)$(schemadir)" - @list='$(schema_DATA)'; test -n "$(schemadir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(schemadir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(schemadir)" || exit $$?; \ - done - -uninstall-schemaDATA: - @$(NORMAL_UNINSTALL) - @list='$(schema_DATA)'; test -n "$(schemadir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(schemadir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(schemadir)" && rm -f $$files install-uiDATA: $(ui_DATA) @$(NORMAL_INSTALL) test -z "$(uidir)" || $(MKDIR_P) "$(DESTDIR)$(uidir)" @@ -586,7 +570,7 @@ check: check-recursive all-am: Makefile $(MANS) $(DATA) installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(schemadir)" "$(DESTDIR)$(uidir)" "$(DESTDIR)$(utilitiesdir)"; do \ + for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(uidir)" "$(DESTDIR)$(utilitiesdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -635,8 +619,7 @@ info: info-recursive info-am: -install-data-am: install-man install-schemaDATA install-uiDATA \ - install-utilitiesDATA +install-data-am: install-man install-uiDATA install-utilitiesDATA install-dvi: install-dvi-recursive @@ -680,8 +663,7 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-man uninstall-schemaDATA uninstall-uiDATA \ - uninstall-utilitiesDATA +uninstall-am: uninstall-man uninstall-uiDATA uninstall-utilitiesDATA uninstall-man: uninstall-man1 @@ -696,16 +678,16 @@ uninstall-man: uninstall-man1 install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man1 install-pdf install-pdf-am install-ps \ - install-ps-am install-schemaDATA install-strip install-uiDATA \ + install-ps-am install-strip install-uiDATA \ install-utilitiesDATA installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-recursive uninstall uninstall-am uninstall-man \ - uninstall-man1 uninstall-schemaDATA uninstall-uiDATA \ - uninstall-utilitiesDATA + uninstall-man1 uninstall-uiDATA uninstall-utilitiesDATA @INTLTOOL_DESKTOP_RULE@ -@INTLTOOL_SCHEMAS_RULE@ +@INTLTOOL_XML_NOMERGE_RULE@ +@GSETTINGS_RULES@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/data/icons/Makefile.in b/data/icons/Makefile.in index b60ce6c..415ccbd 100644 --- a/data/icons/Makefile.in +++ b/data/icons/Makefile.in @@ -38,6 +38,7 @@ am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_GEN = $(am__v_GEN_$(V)) @@ -60,6 +61,8 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +COLORD_CFLAGS = @COLORD_CFLAGS@ +COLORD_LIBS = @COLORD_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -74,11 +77,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ HELP_DIR = @HELP_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -118,6 +121,7 @@ SIMPLE_SCAN_CFLAGS = @SIMPLE_SCAN_CFLAGS@ SIMPLE_SCAN_LIBS = @SIMPLE_SCAN_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ +VALAC = @VALAC@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -139,6 +143,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ diff --git a/data/org.gnome.SimpleScan.gschema.xml.in b/data/org.gnome.SimpleScan.gschema.xml.in new file mode 100644 index 0000000..2a6047f --- /dev/null +++ b/data/org.gnome.SimpleScan.gschema.xml.in @@ -0,0 +1,92 @@ +<schemalist> + <enum id="org.gnome.SimpleScan.ScanDirection"> + <value value="0" nick="top-to-bottom"/> + <value value="1" nick="left-to-right"/> + <value value="2" nick="bottom-to-top"/> + <value value="3" nick="right-to-left"/> + </enum> + <enum id="org.gnome.SimpleScan.PageSide"> + <value value="1" nick="front"/> + <value value="2" nick="back"/> + <value value="3" nick="both"/> + </enum> + + <schema id="org.gnome.SimpleScan" path="/org/gnome/simple-scan/" gettext-domain="simple-scan"> + <key name="window-width" type="i"> + <default>600</default> + <_summary>Window width in pixels</_summary> + </key> + <key name="window-height" type="i"> + <default>400</default> + <_summary>Window height in pixels</_summary> + </key> + <key name="window-is-maximized" type="b"> + <default>false</default> + <_summary>TRUE if the application window is maximized</_summary> + </key> + <key name="selected-device" type="s"> + <default>''</default> + <_summary>Device to scan from</_summary> + <_description>SANE device to acquire images from.</_description> + </key> + <key name="document-type" type="s"> + <default>'photo'</default> + <choices> + <choice value="text"/> + <choice value="photo"/> + </choices> + <_summary>Type of document being scanned</_summary> + <_description>Type of document being scanned. This setting decides on the scan resolution, colors and post-processing.</_description> + </key> + <key name="scan-direction" enum="org.gnome.SimpleScan.ScanDirection"> + <default>'top-to-bottom'</default> + <_summary>Direction of scan</_summary> + <_description>The direction of the scanner across the scanned page.</_description> + </key> + <key name="page-width" type="i"> + <default>595</default> + <_summary>Width of scanned image in pixels</_summary> + <_description>The width of scanned image in pixels. This value is updated to what the last scanned page was.</_description> + </key> + <key name="page-height" type="i"> + <default>842</default> + <_summary>Height of scanned image in pixels</_summary> + <_description>The height of scanned image in pixels. This value is updated to what the last scanned page was.</_description> + </key> + <key name="paper-width" type="i"> + <default>0</default> + <_summary>Width of paper in tenths of a mm</_summary> + <_description>The width of the paper in tenths of a mm (or 0 for automatic paper detection).</_description> + </key> + <key name="paper-height" type="i"> + <default>0</default> + <_summary>Height of paper in tenths of a mm</_summary> + <_description>The height of the paper in tenths of a mm (or 0 for automatic paper detection).</_description> + </key> + <key name="page-dpi" type="i"> + <default>72</default> + <_summary>Resolution of last scanned image</_summary> + <_description>The resolution in dots-per-inch of the previously scanned image.</_description> + </key> + <key name="text-dpi" type="i"> + <default>150</default> + <_summary>Resolution for text scans</_summary> + <_description>The resolution in dots-per-inch to use when scanning text.</_description> + </key> + <key name="photo-dpi" type="i"> + <default>300</default> + <_summary>Resolution for photo scans</_summary> + <_description>The resolution in dots-per-inch to use when scanning photos.</_description> + </key> + <key name="page-side" enum="org.gnome.SimpleScan.PageSide"> + <default>'both'</default> + <_summary>Page side to scan</_summary> + <_description>The page side to scan.</_description> + </key> + <key name="save-directory" type="s"> + <default>''</default> + <_summary>Directory to save files to</_summary> + <_description>The directory to save files to. Defaults to the documents directory if unset.</_description> + </key> + </schema> +</schemalist> diff --git a/data/simple-scan.schemas.in b/data/simple-scan.schemas.in deleted file mode 100644 index 1a5a90d..0000000 --- a/data/simple-scan.schemas.in +++ /dev/null @@ -1,199 +0,0 @@ -<gconfschemafile> - <schemalist> - <schema> - <applyto>/apps/simple-scan/window_width</applyto> - <key>/schemas/apps/simple-scan/window_width</key> - <owner>simple-scan</owner> - <type>int</type> - <default>600</default> - <locale name="C"> - <short>Window width in pixels</short> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/window_height</applyto> - <key>/schemas/apps/simple-scan/window_height</key> - <owner>simple-scan</owner> - <type>int</type> - <default>400</default> - <locale name="C"> - <short>Window height in pixels</short> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/window_is_maximized</applyto> - <key>/schemas/apps/simple-scan/window_is_maximized</key> - <owner>simple-scan</owner> - <type>bool</type> - <default>FALSE</default> - <locale name="C"> - <short>TRUE if the application window is maximized</short> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/selected_device</applyto> - <key>/schemas/apps/simple-scan/selected_device</key> - <owner>simple-scan</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>Device to scan from</short> - <long> - SANE device to acquire images from. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/document_type</applyto> - <key>/schemas/apps/simple-scan/document_type</key> - <owner>simple-scan</owner> - <type>string</type> - <default>photo</default> - <locale name="C"> - <short>Type of document being scanned</short> - <long> - Type of document being scanned. - 'text' for text documents, 'photo' for photos. - This setting decides on the scan resolution, colors and post-processing. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/scan_direction</applyto> - <key>/schemas/apps/simple-scan/scan_direction</key> - <owner>simple-scan</owner> - <type>string</type> - <default>top-to-bottom</default> - <locale name="C"> - <short>Direction of scan</short> - <long> - The direction of the scanner across the scanned page. It can be one of the following: - 'top-to-bottom' - 'bottom-to-top' - 'left-to-right' - 'right-to-left' - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/page_width</applyto> - <key>/schemas/apps/simple-scan/page_width</key> - <owner>simple-scan</owner> - <type>int</type> - <default>595</default> - <locale name="C"> - <short>Width of scanned image in pixels</short> - <long> - The width of scanned image in pixels. This value is updated to what the last scanned page was. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/page_height</applyto> - <key>/schemas/apps/simple-scan/page_height</key> - <owner>simple-scan</owner> - <type>int</type> - <default>842</default> - <locale name="C"> - <short>Height of scanned image in pixels</short> - <long> - The height of scanned image in pixels. This value is updated to what the last scanned page was. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/paper_width</applyto> - <key>/schemas/apps/simple-scan/paper_width</key> - <owner>simple-scan</owner> - <type>int</type> - <default>0</default> - <locale name="C"> - <short>Width of paper in tenths of a mm</short> - <long> - The width of the paper in tenths of a mm (or 0 for automatic paper detection). - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/paper_height</applyto> - <key>/schemas/apps/simple-scan/paper_height</key> - <owner>simple-scan</owner> - <type>int</type> - <default>0</default> - <locale name="C"> - <short>Height of paper in tenths of a mm</short> - <long> - The height of the paper in tenths of a mm (or 0 for automatic paper detection). - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/page_dpi</applyto> - <key>/schemas/apps/simple-scan/page_dpi</key> - <owner>simple-scan</owner> - <type>int</type> - <default>72</default> - <locale name="C"> - <short>Resolution of last scanned image</short> - <long> - The resolution in dots-per-inch of the previously scanned image. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/text_dpi</applyto> - <key>/schemas/apps/simple-scan/text_dpi</key> - <owner>simple-scan</owner> - <type>int</type> - <default>150</default> - <locale name="C"> - <short>Resolution for text scans</short> - <long> - The resolution in dots-per-inch to use when scanning text. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/photo_dpi</applyto> - <key>/schemas/apps/simple-scan/photo_dpi</key> - <owner>simple-scan</owner> - <type>int</type> - <default>300</default> - <locale name="C"> - <short>Resolution for photo scans</short> - <long> - The resolution in dots-per-inch to use when scanning photos. - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/page_side</applyto> - <key>/schemas/apps/simple-scan/page_side</key> - <owner>simple-scan</owner> - <type>string</type> - <default>both</default> - <locale name="C"> - <short>Page side to scan</short> - <long> - The page side to scan. It can be one of the following: - 'both' - 'front' - 'back' - </long> - </locale> - </schema> - <schema> - <applyto>/apps/simple-scan/save_directory</applyto> - <key>/schemas/apps/simple-scan/save_directory</key> - <owner>simple-scan</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>Directory to save files to</short> - <long> - The directory to save files to. Defaults to the documents directory if unset. - </long> - </locale> - </schema> - </schemalist> -</gconfschemafile> diff --git a/data/simple-scan.ui b/data/simple-scan.ui index 7dcd2d7..102a7a8 100644 --- a/data/simple-scan.ui +++ b/data/simple-scan.ui @@ -924,21 +924,21 @@ <object class="GtkListStore" id="page_side_store"> <columns> <!-- column-name side --> - <column type="gchararray"/> + <column type="gint"/> <!-- column-name label --> <column type="gchararray"/> </columns> <data> <row> - <col id="0">both</col> + <col id="0">3</col> <col id="1" translatable="yes" comments="Combo box label for scanning both sides of a page">Front and Back</col> </row> <row> - <col id="0">front</col> + <col id="0">1</col> <col id="1" translatable="yes" comments="Combo box label for scanning the front side of a page">Front</col> </row> <row> - <col id="0">back</col> + <col id="0">2</col> <col id="1" translatable="yes" comments="Combo box label for scanning the back side of a page">Back</col> </row> </data> diff --git a/gnome-doc-utils.make b/gnome-doc-utils.make index bc2a61f..0da2cf9 100644 --- a/gnome-doc-utils.make +++ b/gnome-doc-utils.make @@ -361,7 +361,7 @@ $(_DOC_LC_DOCS) : $(_DOC_C_DOCS) ## @ _DOC_POT ## A pot file -_DOC_POT = $(if $(DOC_MODULE),$(DOC_MODULE).pot) +_DOC_POT = $(if $(DOC_MODULE),$(DOC_MODULE).pot,$(if $(DOC_ID),$(DOC_ID).pot)) .PHONY: pot pot: $(_DOC_POT) $(_DOC_POT): $(_DOC_C_DOCS_NOENT) diff --git a/help/Makefile.in b/help/Makefile.in index 2cd8f12..b9a239a 100644 --- a/help/Makefile.in +++ b/help/Makefile.in @@ -63,6 +63,7 @@ am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_GEN = $(am__v_GEN_$(V)) @@ -85,6 +86,8 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +COLORD_CFLAGS = @COLORD_CFLAGS@ +COLORD_LIBS = @COLORD_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -99,11 +102,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ HELP_DIR = @HELP_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -143,6 +146,7 @@ SIMPLE_SCAN_CFLAGS = @SIMPLE_SCAN_CFLAGS@ SIMPLE_SCAN_LIBS = @SIMPLE_SCAN_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ +VALAC = @VALAC@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -164,6 +168,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ @@ -286,7 +291,7 @@ _DOC_SRC_FIGURES = \ $(foreach fig,$(_DOC_C_FIGURES), $(foreach lc,C $(_DOC_REAL_LINGUAS), \ $(wildcard $(srcdir)/$(lc)/$(patsubst C/%,%,$(fig))) )) -_DOC_POT = $(if $(DOC_MODULE),$(DOC_MODULE).pot) +_DOC_POT = $(if $(DOC_MODULE),$(DOC_MODULE).pot,$(if $(DOC_ID),$(DOC_ID).pot)) ################################################################################ _DOC_HTML_ALL = $(if $(filter html HTML,$(_DOC_REAL_FORMATS)), \ diff --git a/help/POT/POT.po b/help/POT/POT.po index 97044bd..9a2bebb 100644 --- a/help/POT/POT.po +++ b/help/POT/POT.po @@ -1,11 +1,10 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2011-04-21 16:02+1000\n" +"POT-Creation-Date: 2011-06-12 20:11+1000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -31,9 +30,7 @@ msgid "Open <app>Simple Scan</app>." msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanning.page:27(p) -msgid "" -"Press the scan button in the toolbar (or <keyseq><key>Ctrl</key><key>1</" -"key></keyseq>)." +msgid "Press the scan button in the toolbar (or <keyseq><key>Ctrl</key><key>1</key></keyseq>)." msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanning.page:33(p) @@ -41,19 +38,11 @@ msgid "The page will be shown as it is scanned." msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanning.page:37(p) -msgid "" -"Each page you scan is added to the end of your document. To start a new " -"document select <guiseq><gui>Document</gui><gui>New</gui></guiseq>. " -"Individual pages can be deleted by right clicking a page or pressing the " -"<key>Delete</key> key." +msgid "Each page you scan is added to the end of your document. To start a new document select <guiseq><gui>Document</gui><gui>New</gui></guiseq>. Individual pages can be deleted by right clicking a page or pressing the <key>Delete</key> key." msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanning.page:42(p) -msgid "" -"The type of scan can be changed from the <guiseq><gui>Document</" -"gui><gui>Scan</gui></guiseq> menu. Choose <gui>Text</gui> if you want the " -"document to be quickly scanned in black and white or <gui>Photo</gui> for a " -"high resolution color scan." +msgid "The type of scan can be changed from the <guiseq><gui>Document</gui><gui>Scan</gui></guiseq> menu. Choose <gui>Text</gui> if you want the document to be quickly scanned in black and white or <gui>Photo</gui> for a high resolution color scan." msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanning.page:47(p) @@ -65,17 +54,11 @@ msgid "Selecting a Scanner" msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanner.page:11(p) -msgid "" -"If you have multiple scanners you can change which scanner is selected from " -"the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." +msgid "If you have multiple scanners you can change which scanner is selected from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." msgstr "" #: /home/bob/bzr/simple-scan/help/C/scanner.page:15(p) -msgid "" -"Your local scanners are automatically detected each time you start " -"<app>Simple Scan</app> and each time you plug in USB scanner. If you have a " -"network scanner you will need to restart <app>Simple Scan</app> for it to be " -"detected." +msgid "Your local scanners are automatically detected each time you start <app>Simple Scan</app> and each time you plug in USB scanner. If you have a network scanner you will need to restart <app>Simple Scan</app> for it to be detected." msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:9(title) @@ -83,10 +66,7 @@ msgid "Saving to a File" msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:11(p) -msgid "" -"To save the current document to a file use the <guiseq><gui>Document</" -"gui><gui>Save</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>S</key></" -"keyseq>). When you save, there is a choice of three file types." +msgid "To save the current document to a file use the <guiseq><gui>Document</gui><gui>Save</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>S</key></keyseq>). When you save, there is a choice of three file types." msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:17(title) @@ -94,10 +74,7 @@ msgid "Portable Document Format (PDF)" msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:18(p) -msgid "" -"A PDF can contain multiple pages (like a book) and is easy to distribute to " -"other people. Most people do not have software to modify PDF documents so " -"this format is best used for archiving." +msgid "A PDF can contain multiple pages (like a book) and is easy to distribute to other people. Most people do not have software to modify PDF documents so this format is best used for archiving." msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:19(p) @@ -109,11 +86,7 @@ msgid "JPEG" msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:23(p) -msgid "" -"JPEG file is the file format used by digital cameras and is very small and " -"so easy to distribute. Most people have software to modify JPEG photos and " -"this format is suitable for uploading to social networking sites. If you " -"have scanned multiple pages then a JPEG file will be written for each page." +msgid "JPEG file is the file format used by digital cameras and is very small and so easy to distribute. Most people have software to modify JPEG photos and this format is suitable for uploading to social networking sites. If you have scanned multiple pages then a JPEG file will be written for each page." msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:24(p) @@ -125,10 +98,7 @@ msgid "PNG" msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:28(p) -msgid "" -"PNG files contain the raw data from the scanner. This makes them much larger " -"than JPEG files and not suitable for distributing. If you have scanned " -"multiple pages then a PNG file will be written for each page." +msgid "PNG files contain the raw data from the scanner. This makes them much larger than JPEG files and not suitable for distributing. If you have scanned multiple pages then a PNG file will be written for each page." msgstr "" #: /home/bob/bzr/simple-scan/help/C/save.page:29(p) @@ -140,10 +110,7 @@ msgid "Rotating Pages" msgstr "" #: /home/bob/bzr/simple-scan/help/C/rotate.page:11(p) -msgid "" -"To rotate a page use the rotation buttons in the toolbar or the <key>[</key> " -"and <key>]</key> keys. Each new page that is scanned will use the previous " -"rotation." +msgid "To rotate a page use the rotation buttons in the toolbar or the <key>[</key> and <key>]</key> keys. Each new page that is scanned will use the previous rotation." msgstr "" #: /home/bob/bzr/simple-scan/help/C/reorder.page:9(title) @@ -151,9 +118,7 @@ msgid "Reordering Pages" msgstr "" #: /home/bob/bzr/simple-scan/help/C/reorder.page:11(p) -msgid "" -"To move a page, select it and move the page left or right using the <key><" -"</key> and <key>></key> keys." +msgid "To move a page, select it and move the page left or right using the <key><</key> and <key>></key> keys." msgstr "" #: /home/bob/bzr/simple-scan/help/C/reorder.page:14(p) @@ -165,9 +130,7 @@ msgid "Printing" msgstr "" #: /home/bob/bzr/simple-scan/help/C/print.page:11(p) -msgid "" -"To print the current document use the <guiseq><gui>Document</gui><gui>Print</" -"gui></guiseq> menu (<keyseq><key>Ctrl</key><key>P</key></keyseq>)." +msgid "To print the current document use the <guiseq><gui>Document</gui><gui>Print</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>P</key></keyseq>)." msgstr "" #: /home/bob/bzr/simple-scan/help/C/email.page:9(title) @@ -175,17 +138,11 @@ msgid "Sending via Email" msgstr "" #: /home/bob/bzr/simple-scan/help/C/email.page:11(p) -msgid "" -"To email the current document use the <guiseq><gui>Document</gui><gui>Email</" -"gui></guiseq> menu (<keyseq><key>Ctrl</key><key>E</key></keyseq>). Your " -"email program will be opened with a new message containing the scanned " -"document as an attachment." +msgid "To email the current document use the <guiseq><gui>Document</gui><gui>Email</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>E</key></keyseq>). Your email program will be opened with a new message containing the scanned document as an attachment." msgstr "" #: /home/bob/bzr/simple-scan/help/C/email.page:15(p) -msgid "" -"If the document type is set to text the email will have a PDF attachment " -"otherwise the email will have a JPEG attachment for each page." +msgid "If the document type is set to text the email will have a PDF attachment otherwise the email will have a JPEG attachment for each page." msgstr "" #: /home/bob/bzr/simple-scan/help/C/email.page:18(p) @@ -197,10 +154,7 @@ msgid "Setting the Scan Resolution" msgstr "" #: /home/bob/bzr/simple-scan/help/C/dpi.page:11(p) -msgid "" -"By default text documents will be scanned at 200 dots per inch (dpi) and " -"photos at 400 dpi. To change these settings open the preferences from the " -"<guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." +msgid "By default text documents will be scanned at 200 dots per inch (dpi) and photos at 400 dpi. To change these settings open the preferences from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." msgstr "" #: /home/bob/bzr/simple-scan/help/C/crop.page:9(title) @@ -208,22 +162,15 @@ msgid "Cropping" msgstr "" #: /home/bob/bzr/simple-scan/help/C/crop.page:11(p) -msgid "" -"To use only part of the scanned page enable crop by selecting the crop " -"button in the toolbar. A mask will be shown over the current page with the " -"area not being used shown in gray." +msgid "To use only part of the scanned page enable crop by selecting the crop button in the toolbar. A mask will be shown over the current page with the area not being used shown in gray." msgstr "" #: /home/bob/bzr/simple-scan/help/C/crop.page:15(p) -msgid "" -"The crop area can be adjusted by clicking on the inside of the crop area " -"border and dragging the mouse." +msgid "The crop area can be adjusted by clicking on the inside of the crop area border and dragging the mouse." msgstr "" #: /home/bob/bzr/simple-scan/help/C/crop.page:18(p) -msgid "" -"Fixed crop sizes can be chosen from the <guiseq><gui>Page</gui><gui>Crop</" -"gui></guiseq> menu that match commonly used paper sizes." +msgid "Fixed crop sizes can be chosen from the <guiseq><gui>Page</gui><gui>Crop</gui></guiseq> menu that match commonly used paper sizes." msgstr "" #: /home/bob/bzr/simple-scan/help/C/crop.page:21(p) @@ -235,17 +182,11 @@ msgid "Using an Automatic Document Feeder" msgstr "" #: /home/bob/bzr/simple-scan/help/C/adf.page:11(p) -msgid "" -"If your scanner has an Automatic Document Feeder (ADF) you can scan all the " -"pages by selecting the <guiseq><gui>Document</gui><gui>Scan</gui><gui>All " -"Pages From Feeder</gui></guiseq> menu." +msgid "If your scanner has an Automatic Document Feeder (ADF) you can scan all the pages by selecting the <guiseq><gui>Document</gui><gui>Scan</gui><gui>All Pages From Feeder</gui></guiseq> menu." msgstr "" #: /home/bob/bzr/simple-scan/help/C/adf.page:14(p) -msgid "" -"By default both sides of the paper will be scanned if your scanned supports " -"this. Single side scanning can be configured from the <guiseq><gui>Document</" -"gui><gui>Preferences</gui></guiseq> menu." +msgid "By default both sides of the paper will be scanned if your scanned supports this. Single side scanning can be configured from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." msgstr "" #: /home/bob/bzr/simple-scan/help/C/index.page:7(name) @@ -273,20 +214,15 @@ msgid "Using the Document" msgstr "" #: /home/bob/bzr/simple-scan/help/C/legal.xml:3(p) -msgid "" -"This work is licensed under a <link href=\"http://creativecommons.org/" -"licenses/by-sa/3.0/\">Creative Commons Attribution-Share Alike 3.0 Unported " -"License</link>." +msgid "This work is licensed under a <link href=\"http://creativecommons.org/licenses/by-sa/3.0/\">Creative Commons Attribution-Share Alike 3.0 Unported License</link>." msgstr "" #: /home/bob/bzr/simple-scan/help/C/legal.xml:6(p) -msgid "" -"As a special exception, the copyright holders give you permission to copy, " -"modify, and distribute the example code contained in this document under the " -"terms of your choosing, without restriction." +msgid "As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this document under the terms of your choosing, without restriction." msgstr "" #. Put one translator per line, in the form of NAME <EMAIL>, YEAR1, YEAR2 #: /home/bob/bzr/simple-scan/help/C/legal.xml:0(None) msgid "translator-credits" msgstr "" + diff --git a/help/de/adf.page b/help/de/adf.page index ebd609b..f8aebb5 100644 --- a/help/de/adf.page +++ b/help/de/adf.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#acquire"/> </info> - <title>Verwendung eines automatischen Dokumenteneinzugs</title> + <title>Using an Automatic Document Feeder</title> <p> If your scanner has an Automatic Document Feeder (ADF) you can scan all the pages by selecting the <guiseq><gui>Document</gui><gui>Scan</gui><gui>All Pages From Feeder</gui></guiseq> menu. diff --git a/help/de/crop.page b/help/de/crop.page index 16af258..0ba09c7 100644 --- a/help/de/crop.page +++ b/help/de/crop.page @@ -5,12 +5,19 @@ <link type="guide" xref="index#modify"/> </info> - <title>Zuschneiden</title> + <title>Cropping</title> - <p>Um nur einen Teil der eingescannten Seite zu verwenden, können Sie mit dem Zuschneiden-Knopf in der Werkzeugleiste diese auf die gewünschte Größe zuschneiden. Eine Maske wird über der aktuellen Seite angezeigt, wobei der nicht zu verwendende Teil in Grau dargestellt wird.</p> - <p>Sie können den Zuschnittbereich anpassen, indem Sie innerhalb der Umrandung dieses Bereichs mit der Maus klicken und die Maus dann ziehen.</p> + <p> + To use only part of the scanned page enable crop by selecting the crop button in the toolbar. + A mask will be shown over the current page with the area not being used shown in gray. + </p> + <p> + The crop area can be adjusted by clicking on the inside of the crop area border and dragging the mouse. + </p> <p> Fixed crop sizes can be chosen from the <guiseq><gui>Page</gui><gui>Crop</gui></guiseq> menu that match commonly used paper sizes. </p> - <p>Jede neu eingescannte Seite verwendet den Zuschnitt der vorherigen Seite.</p> + <p> + Each new page that is scanned will use the previous crop. + </p> </page> diff --git a/help/de/de.po b/help/de/de.po index 40b36d7..9a2bebb 100644 --- a/help/de/de.po +++ b/help/de/de.po @@ -1,449 +1,228 @@ -# German translation of the Simple Scan manual. -# Mario Blättermann <mariobl@gnome.org>, 2010. -# msgid "" msgstr "" -"Project-Id-Version: simple scan docs\n" -"POT-Creation-Date: 2010-10-10 21:55+0200\n" -"PO-Revision-Date: 2010-10-11 20:17+0100\n" -"Last-Translator: Mario Blättermann <mariobl@gnome.org>\n" -"Language-Team: German <gnome-de@gnome.org>\n" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2011-06-12 20:11+1000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: German\n" -"X-Poedit-Country: GERMANY\n" -#: scanning.page:6(title) +#: /home/bob/bzr/simple-scan/help/C/scanning.page:6(title) msgid "0" -msgstr "0" +msgstr "" -#: scanning.page:10(title) +#: /home/bob/bzr/simple-scan/help/C/scanning.page:10(title) msgid "Scanning a Page" -msgstr "Scannen einer Seite" +msgstr "" -#: scanning.page:12(p) +#: /home/bob/bzr/simple-scan/help/C/scanning.page:12(p) msgid "To scan a document from your scanner:" -msgstr "So scannen Sie ein Dokument mit ihrem Scanner ein:" +msgstr "" -#: scanning.page:17(p) +#: /home/bob/bzr/simple-scan/help/C/scanning.page:17(p) msgid "Connect the scanner to your computer." -msgstr "Schließen Sie den Scanner an Ihren Rechner an." - -#: scanning.page:23(app) scanner.page:16(app) scanner.page:17(app) -msgid "Simple Scan" -msgstr "Simple Scan" - -#: scanning.page:22(p) -msgid "Open <placeholder-1/>." -msgstr "Öffnen Sie <placeholder-1/>." - -#: scanning.page:28(key) save.page:12(key) print.page:12(key) -#: email.page:12(key) -msgid "Ctrl" -msgstr "Strg" +msgstr "" -#: scanning.page:28(key) -msgid "1" -msgstr "1" +#: /home/bob/bzr/simple-scan/help/C/scanning.page:22(p) +msgid "Open <app>Simple Scan</app>." +msgstr "" -#: scanning.page:27(p) -msgid "" -"Press the scan button in the toolbar (or <keyseq><placeholder-1/" -"><placeholder-2/></keyseq>)." +#: /home/bob/bzr/simple-scan/help/C/scanning.page:27(p) +msgid "Press the scan button in the toolbar (or <keyseq><key>Ctrl</key><key>1</key></keyseq>)." msgstr "" -"Klicken Sie auf den Scannen-Knopf in der Werkzeugleiste (oder " -"<keyseq><placeholder-1/><placeholder-2/></keyseq>)." -#: scanning.page:33(p) +#: /home/bob/bzr/simple-scan/help/C/scanning.page:33(p) msgid "The page will be shown as it is scanned." -msgstr "Jede Seite wird so angezeigt, wie sie gescannt wurde." - -#: scanning.page:38(gui) scanning.page:43(gui) scanner.page:12(gui) -#: save.page:12(gui) print.page:12(gui) email.page:12(gui) dpi.page:13(gui) -#: adf.page:12(gui) adf.page:16(gui) -msgid "Document" -msgstr "Dokument" - -#: scanning.page:38(gui) -msgid "New" -msgstr "Neu" - -#: scanning.page:39(key) reorder.page:15(key) -msgid "Delete" -msgstr "Löschen" - -#: scanning.page:37(p) -msgid "" -"Each page you scan is added to the end of your document. To start a new " -"document select <guiseq><placeholder-1/><placeholder-2/></guiseq>. Individual " -"pages can be deleted by right clicking a page or pressing the <placeholder-3/" -"> key." msgstr "" -"Jede eingescannte Seite wird an das Ende Ihres Dokuments angefügt. Um ein " -"neues Dokument zu beginnen, wählen Sie <guiseq><placeholder-1/><placeholder-2/" -"></guiseq>. Seiten können einzeln entfernt werden, indem Sie mit der rechten " -"Maustaste auf eine Seite klicken oder die <placeholder-3/>-Taste drücken." - -#: scanning.page:43(gui) adf.page:12(gui) -msgid "Scan" -msgstr "Scannen" -#: scanning.page:44(gui) -msgid "Text" -msgstr "Text" - -#: scanning.page:44(gui) -msgid "Photo" -msgstr "Foto" - -#: scanning.page:42(p) -msgid "" -"The type of scan can be changed from the <guiseq><placeholder-1/" -"><placeholder-2/></guiseq> menu. Choose <placeholder-3/> if you want the " -"document to be quickly scanned in black and white or <placeholder-4/> for a " -"high resolution color scan." +#: /home/bob/bzr/simple-scan/help/C/scanning.page:37(p) +msgid "Each page you scan is added to the end of your document. To start a new document select <guiseq><gui>Document</gui><gui>New</gui></guiseq>. Individual pages can be deleted by right clicking a page or pressing the <key>Delete</key> key." msgstr "" -"Der Scantyp kann im Menü <guiseq><placeholder-1/><placeholder-2/></guiseq> " -"geändert werden. Wählen Sie <placeholder-3/>, wenn das Dokument schnell in " -"Schwarzweiß eingescannt werden soll oder <placeholder-4/> für einen " -"hochauflösenden Farbscan." -#: scanning.page:48(key) -msgid "Escape" -msgstr "Esc" +#: /home/bob/bzr/simple-scan/help/C/scanning.page:42(p) +msgid "The type of scan can be changed from the <guiseq><gui>Document</gui><gui>Scan</gui></guiseq> menu. Choose <gui>Text</gui> if you want the document to be quickly scanned in black and white or <gui>Photo</gui> for a high resolution color scan." +msgstr "" -#: scanning.page:47(p) -msgid "To stop the scan at any time press <placeholder-1/>." -msgstr "Um den Scanvorgang abzubrechen, drücken Sie <placeholder-1/>." +#: /home/bob/bzr/simple-scan/help/C/scanning.page:47(p) +msgid "To stop the scan at any time press <key>Escape</key>." +msgstr "" -#: scanner.page:9(title) +#: /home/bob/bzr/simple-scan/help/C/scanner.page:9(title) msgid "Selecting a Scanner" -msgstr "Einen Scanner auswählen" - -#: scanner.page:12(gui) dpi.page:13(gui) adf.page:16(gui) -msgid "Preferences" -msgstr "Einstellungen" +msgstr "" -#: scanner.page:11(p) -msgid "" -"If you have multiple scanners you can change which scanner is selected from " -"the <guiseq><placeholder-1/><placeholder-2/></guiseq> menu." +#: /home/bob/bzr/simple-scan/help/C/scanner.page:11(p) +msgid "If you have multiple scanners you can change which scanner is selected from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." msgstr "" -"Falls Sie über mehrere Scanner verfügen, können Sie im Menü " -"<guiseq><placeholder-1/><placeholder-2/></guiseq> wählen, welcher davon " -"verwendet werden soll." -#: scanner.page:15(p) -msgid "" -"Your local scanners are automatically detected each time you start " -"<placeholder-1/> and each time you plug in USB scanner. If you have a network " -"scanner you will need to restart <placeholder-2/> for it to be detected." +#: /home/bob/bzr/simple-scan/help/C/scanner.page:15(p) +msgid "Your local scanners are automatically detected each time you start <app>Simple Scan</app> and each time you plug in USB scanner. If you have a network scanner you will need to restart <app>Simple Scan</app> for it to be detected." msgstr "" -"Ihre lokalen Scanner werden jedes Mal beim Start von <placeholder-1/> und bei " -"jedem Anschließen eines USB-Scanners automatisch erkannt. Wenn Sie einen " -"Netzwerkscanner haben, müssen Sie <placeholder-2/> neu starten, damit dieser " -"erkannt werden kann." -#: save.page:9(title) +#: /home/bob/bzr/simple-scan/help/C/save.page:9(title) msgid "Saving to a File" -msgstr "Speichern in einer Datei" - -#: save.page:12(gui) -msgid "Save" -msgstr "Speichern " - -#: save.page:12(key) -msgid "S" -msgstr "S" +msgstr "" -#: save.page:11(p) -msgid "" -"To save the current document to a file use the <guiseq><placeholder-1/" -"><placeholder-2/></guiseq> menu (<keyseq><placeholder-3/><placeholder-4/></" -"keyseq>). When you save, there is a choice of three file types." +#: /home/bob/bzr/simple-scan/help/C/save.page:11(p) +msgid "To save the current document to a file use the <guiseq><gui>Document</gui><gui>Save</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>S</key></keyseq>). When you save, there is a choice of three file types." msgstr "" -"Um das aktuelle Dokument zu speichern, wählen Sie <guiseq><placeholder-1/" -"><placeholder-2/></guiseq> (<keyseq><placeholder-3/><placeholder-4/></" -"keyseq>). Beim Speichern können Sie aus drei Dateitypen wählen." -#: save.page:17(title) +#: /home/bob/bzr/simple-scan/help/C/save.page:17(title) msgid "Portable Document Format (PDF)" -msgstr "Portable Document Format (PDF)" +msgstr "" -#: save.page:18(p) -msgid "" -"A PDF can contain multiple pages (like a book) and is easy to distribute to " -"other people. Most people do not have software to modify PDF documents so " -"this format is best used for archiving." +#: /home/bob/bzr/simple-scan/help/C/save.page:18(p) +msgid "A PDF can contain multiple pages (like a book) and is easy to distribute to other people. Most people do not have software to modify PDF documents so this format is best used for archiving." msgstr "" -"Ein PDF kann mehrere Seiten enthalten (wie ein Buch) und lässt sich auf " -"einfache Art und Weise an Andere weitergeben. Die meisten Benutzer verfügen " -"nicht über Software zum Bearbeiten von PDF-Dokumenten, so dass sich dieses " -"Format bestens zur Archivierung eignet." -#: save.page:19(p) +#: /home/bob/bzr/simple-scan/help/C/save.page:19(p) msgid "Use this type if you have scanned multiple pages of text." msgstr "" -"Verwenden Sie diesen Typ, wenn Sie mehrere Textseiten eingescannt haben." -#: save.page:22(title) +#: /home/bob/bzr/simple-scan/help/C/save.page:22(title) msgid "JPEG" -msgstr "JPEG" +msgstr "" -#: save.page:23(p) -msgid "" -"JPEG file is the file format used by digital cameras and is very small and so " -"easy to distribute. Most people have software to modify JPEG photos and this " -"format is suitable for uploading to social networking sites. If you have " -"scanned multiple pages then a JPEG file will be written for each page." -msgstr "" -"JPEG ist das von Digitalkameras verwendete Dateiformat. Es ist recht klein " -"und bestens für die Weitergabe geeignet. Die meisten Benutzer verfügen über " -"Software zum Bearbeiten von JPEG-Fotos, außerdem lässt es sich einfach auf " -"Webseiten sozialer Netzwerke hochladen. Falls Sie mehrere Seiten eingescannt " -"haben, wird für jede Seite eine JPEG-Datei erzeugt." - -#: save.page:24(p) +#: /home/bob/bzr/simple-scan/help/C/save.page:23(p) +msgid "JPEG file is the file format used by digital cameras and is very small and so easy to distribute. Most people have software to modify JPEG photos and this format is suitable for uploading to social networking sites. If you have scanned multiple pages then a JPEG file will be written for each page." +msgstr "" + +#: /home/bob/bzr/simple-scan/help/C/save.page:24(p) msgid "Use this type if you want to modify or upload the scanned images." msgstr "" -"Verwenden Sie diesen Typ, wenn Sie die eingescannten Bilder bearbeiten oder " -"hochladen wollen." -#: save.page:27(title) +#: /home/bob/bzr/simple-scan/help/C/save.page:27(title) msgid "PNG" -msgstr "PNG" +msgstr "" -#: save.page:28(p) -msgid "" -"PNG files contain the raw data from the scanner. This makes them much larger " -"than JPEG files and not suitable for distributing. If you have scanned " -"multiple pages then a PNG file will be written for each page." +#: /home/bob/bzr/simple-scan/help/C/save.page:28(p) +msgid "PNG files contain the raw data from the scanner. This makes them much larger than JPEG files and not suitable for distributing. If you have scanned multiple pages then a PNG file will be written for each page." msgstr "" -"PNG-Dateien enthalten die Rohdaten aus dem Scanner. Dadurch sind sie " -"wesentlich größer als JPEG-Dateien und für die Weitergabe ungeeignet. Wenn " -"Sie mehrere Seiten einscannen, wird für jede Seite eine PNG-Datei erzeugt." -#: save.page:29(p) +#: /home/bob/bzr/simple-scan/help/C/save.page:29(p) msgid "Use this type if you need high resolution files for editing" msgstr "" -"Verwenden Sie diesen Typ, wenn sie hochauflösende Dateien zur " -"Weiterverarbeitung benötigen." -#: rotate.page:9(title) +#: /home/bob/bzr/simple-scan/help/C/rotate.page:9(title) msgid "Rotating Pages" -msgstr "Seiten drehen" - -#: rotate.page:12(key) -msgid "[" -msgstr "[" - -#: rotate.page:12(key) -msgid "]" -msgstr "]" +msgstr "" -#: rotate.page:11(p) -msgid "" -"To rotate a page use the rotation buttons in the toolbar or the " -"<placeholder-1/> and <placeholder-2/> keys. Each new page that is scanned " -"will use the previous rotation." +#: /home/bob/bzr/simple-scan/help/C/rotate.page:11(p) +msgid "To rotate a page use the rotation buttons in the toolbar or the <key>[</key> and <key>]</key> keys. Each new page that is scanned will use the previous rotation." msgstr "" -"Um eine Seite zu drehen, verwenden Sie die Drehknöpfe in der Werkzeugleiste " -"oder die Tasten <placeholder-1/> und <placeholder-2/>. Jede neu eingescannte " -"Seite übernimmt dann die gewählte Drehung." -#: reorder.page:9(title) +#: /home/bob/bzr/simple-scan/help/C/reorder.page:9(title) msgid "Reordering Pages" -msgstr "Seiten neu anordnen" - -#: reorder.page:12(key) -msgid "<" -msgstr "<" - -#: reorder.page:12(key) -msgid ">" -msgstr ">" +msgstr "" -#: reorder.page:11(p) -msgid "" -"To move a page, select it and move the page left or right using the " -"<placeholder-1/> and <placeholder-2/> keys." +#: /home/bob/bzr/simple-scan/help/C/reorder.page:11(p) +msgid "To move a page, select it and move the page left or right using the <key><</key> and <key>></key> keys." msgstr "" -"Um eine Seite zu verschieben, wählen Sie sie aus und verschieben Sie sie mit " -"den Tasten <placeholder-1/> und <placeholder-2/> nach rechts oder links." -#: reorder.page:14(p) -msgid "To remove the selected page use the <placeholder-1/> key." +#: /home/bob/bzr/simple-scan/help/C/reorder.page:14(p) +msgid "To remove the selected page use the <key>Delete</key> key." msgstr "" -"Um die ausgewählte Seite zu entfernen, verwenden Sie die <placeholder-1/>-" -"Taste." -#: print.page:9(title) +#: /home/bob/bzr/simple-scan/help/C/print.page:9(title) msgid "Printing" -msgstr "Drucken" - -#: print.page:12(gui) -msgid "Print" -msgstr "Drucken" - -#: print.page:12(key) -msgid "P" -msgstr "P" - -#: print.page:11(p) -msgid "" -"To print the current document use the <guiseq><placeholder-1/><placeholder-2/" -"></guiseq> menu (<keyseq><placeholder-3/><placeholder-4/></keyseq>)." msgstr "" -"Um das aktuelle Dokument zu drucken, wählen Sie <guiseq><placeholder-1/" -"><placeholder-2/></guiseq> (<keyseq><placeholder-3/><placeholder-4/></" -"keyseq>)." -#: index.page:7(name) -msgid "Robert Ancell" -msgstr "Robert Ancell" - -#: index.page:8(email) -msgid "robert.ancell@gmail.com" -msgstr "robert.ancell@gmail.com" +#: /home/bob/bzr/simple-scan/help/C/print.page:11(p) +msgid "To print the current document use the <guiseq><gui>Document</gui><gui>Print</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>P</key></keyseq>)." +msgstr "" -#: index.page:13(title) -msgid "Simple Scan Help" -msgstr "Hilfe zu Simple Scan" +#: /home/bob/bzr/simple-scan/help/C/email.page:9(title) +msgid "Sending via Email" +msgstr "" -#: index.page:16(title) -msgid "Scanning Pages" -msgstr "Scannen von Seiten" +#: /home/bob/bzr/simple-scan/help/C/email.page:11(p) +msgid "To email the current document use the <guiseq><gui>Document</gui><gui>Email</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>E</key></keyseq>). Your email program will be opened with a new message containing the scanned document as an attachment." +msgstr "" -#: index.page:20(title) -msgid "Modifying the Document" -msgstr "Bearbeiten des Dokuments" +#: /home/bob/bzr/simple-scan/help/C/email.page:15(p) +msgid "If the document type is set to text the email will have a PDF attachment otherwise the email will have a JPEG attachment for each page." +msgstr "" -#: index.page:24(title) -msgid "Using the Document" -msgstr "Das Dokument verwenden" +#: /home/bob/bzr/simple-scan/help/C/email.page:18(p) +msgid "See <link xref=\"save\"/> for more information about file formats." +msgstr "" -#: email.page:9(title) -msgid "Sending via Email" -msgstr "Per E-Mail versenden" +#: /home/bob/bzr/simple-scan/help/C/dpi.page:9(title) +msgid "Setting the Scan Resolution" +msgstr "" -#: email.page:12(gui) -msgid "Email" -msgstr "E-Mail" +#: /home/bob/bzr/simple-scan/help/C/dpi.page:11(p) +msgid "By default text documents will be scanned at 200 dots per inch (dpi) and photos at 400 dpi. To change these settings open the preferences from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." +msgstr "" -#: email.page:12(key) -msgid "E" -msgstr "E" +#: /home/bob/bzr/simple-scan/help/C/crop.page:9(title) +msgid "Cropping" +msgstr "" -#: email.page:11(p) -msgid "" -"To email the current document use the <guiseq><placeholder-1/><placeholder-2/" -"></guiseq> menu (<keyseq><placeholder-3/><placeholder-4/></keyseq>). Your " -"email program will be opened with a new message containing the scanned " -"document as an attachment." +#: /home/bob/bzr/simple-scan/help/C/crop.page:11(p) +msgid "To use only part of the scanned page enable crop by selecting the crop button in the toolbar. A mask will be shown over the current page with the area not being used shown in gray." msgstr "" -"Um das aktuelle Dokument per E-Mail zu versenden, wählen Sie " -"<guiseq><placeholder-1/><placeholder-2/></guiseq> (<keyseq><placeholder-3/" -"><placeholder-4/></keyseq>). Ihr E-Mail-Programm wird mit einer neuen " -"Nachricht geöffnet, die das eingescannte Dokument als Anhang enthält." -#: email.page:15(p) -msgid "" -"If the document type is set to text the email will have a PDF attachment " -"otherwise the email will have a JPEG attachment for each page." +#: /home/bob/bzr/simple-scan/help/C/crop.page:15(p) +msgid "The crop area can be adjusted by clicking on the inside of the crop area border and dragging the mouse." msgstr "" -"Falls der Dokumenttyp auf Text gesetzt ist, dann wird der E-Mail-Anhang im " -"PDF-Format versendet, anderenfalls wird für jede Seite ein separater JPEG-" -"Anhang erzeugt." -#: email.page:18(p) -msgid "See <link xref=\"save\"/> for more information about file formats." +#: /home/bob/bzr/simple-scan/help/C/crop.page:18(p) +msgid "Fixed crop sizes can be chosen from the <guiseq><gui>Page</gui><gui>Crop</gui></guiseq> menu that match commonly used paper sizes." msgstr "" -"In <link xref=\"save\"/> finden Sie weitere Informationen über Dateiformate." -#: dpi.page:9(title) -msgid "Setting the Scan Resolution" -msgstr "Festlegen der Auflösung" +#: /home/bob/bzr/simple-scan/help/C/crop.page:21(p) +msgid "Each new page that is scanned will use the previous crop." +msgstr "" -#: dpi.page:11(p) -msgid "" -"By default text documents will be scanned at 200 dots per inch (dpi) and " -"photos at 400 dpi. To change these settings open the preferences from the " -"<guiseq><placeholder-1/><placeholder-2/></guiseq> menu." +#: /home/bob/bzr/simple-scan/help/C/adf.page:9(title) +msgid "Using an Automatic Document Feeder" msgstr "" -"Standardmäßig werden Dokumente mit 200 dpi (Punkte pro Zoll) eingescannt und " -"Fotos mit 400 dpi. Um diese Einstellungen zu ändern, öffnen Sie die " -"Einstellungen mit <guiseq><placeholder-1/><placeholder-2/></guiseq>." -#: crop.page:9(title) -msgid "Cropping" -msgstr "Zuschneiden" +#: /home/bob/bzr/simple-scan/help/C/adf.page:11(p) +msgid "If your scanner has an Automatic Document Feeder (ADF) you can scan all the pages by selecting the <guiseq><gui>Document</gui><gui>Scan</gui><gui>All Pages From Feeder</gui></guiseq> menu." +msgstr "" -#: crop.page:11(p) -msgid "" -"To use only part of the scanned page enable crop by selecting the crop button " -"in the toolbar. A mask will be shown over the current page with the area not " -"being used shown in gray." +#: /home/bob/bzr/simple-scan/help/C/adf.page:14(p) +msgid "By default both sides of the paper will be scanned if your scanned supports this. Single side scanning can be configured from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu." msgstr "" -"Um nur einen Teil der eingescannten Seite zu verwenden, können Sie mit dem " -"Zuschneiden-Knopf in der Werkzeugleiste diese auf die gewünschte Größe " -"zuschneiden. Eine Maske wird über der aktuellen Seite angezeigt, wobei der " -"nicht zu verwendende Teil in Grau dargestellt wird." -#: crop.page:15(p) -msgid "" -"The crop area can be adjusted by clicking on the inside of the crop area " -"border and dragging the mouse." +#: /home/bob/bzr/simple-scan/help/C/index.page:7(name) +msgid "Robert Ancell" msgstr "" -"Sie können den Zuschnittbereich anpassen, indem Sie innerhalb der Umrandung " -"dieses Bereichs mit der Maus klicken und die Maus dann ziehen." -#: crop.page:19(gui) -msgid "Page" -msgstr "Seite" +#: /home/bob/bzr/simple-scan/help/C/index.page:8(email) +msgid "robert.ancell@gmail.com" +msgstr "" -#: crop.page:19(gui) -msgid "Crop" -msgstr "Zuschneiden" +#: /home/bob/bzr/simple-scan/help/C/index.page:13(title) +msgid "Simple Scan Help" +msgstr "" -#: crop.page:18(p) -msgid "" -"Fixed crop sizes can be chosen from the <guiseq><placeholder-1/" -"><placeholder-2/></guiseq> menu that match commonly used paper sizes." +#: /home/bob/bzr/simple-scan/help/C/index.page:16(title) +msgid "Scanning Pages" msgstr "" -"Voreingestellte Zuschnittgrößen wählen Sie im Menü <guiseq><placeholder-1/" -"><placeholder-2/></guiseq>, das Ihnen häufig verwendete Papiergrößen zur " -"Auswahl anbietet." -#: crop.page:21(p) -msgid "Each new page that is scanned will use the previous crop." +#: /home/bob/bzr/simple-scan/help/C/index.page:20(title) +msgid "Modifying the Document" msgstr "" -"Jede neu eingescannte Seite verwendet den Zuschnitt der vorherigen Seite." -#: adf.page:9(title) -msgid "Using an Automatic Document Feeder" -msgstr "Verwendung eines automatischen Dokumenteneinzugs" +#: /home/bob/bzr/simple-scan/help/C/index.page:24(title) +msgid "Using the Document" +msgstr "" -#: adf.page:12(gui) -msgid "All Pages From Feeder" -msgstr "Alle Seiten aus dem Papiereinzug" +#: /home/bob/bzr/simple-scan/help/C/legal.xml:3(p) +msgid "This work is licensed under a <link href=\"http://creativecommons.org/licenses/by-sa/3.0/\">Creative Commons Attribution-Share Alike 3.0 Unported License</link>." +msgstr "" -#: adf.page:11(p) -msgid "" -"If your scanner has an Automatic Document Feeder (ADF) you can scan all the " -"pages by selecting the <guiseq><placeholder-1/><placeholder-2/><placeholder-3/" -"></guiseq> menu." +#: /home/bob/bzr/simple-scan/help/C/legal.xml:6(p) +msgid "As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this document under the terms of your choosing, without restriction." msgstr "" -"Falls Ihr Scanner mit einem automatischen Dokumenteneinzug ausgestattet ist, " -"wählen Sie im Menü <guiseq><placeholder-1/><placeholder-2/><placeholder-3/></" -"guiseq>, um alle Seiten einzuscannen." -#: adf.page:14(p) -msgid "" -"By default both sides of the paper will be scanned if your scanned supports " -"this. Single side scanning can be configured from the <guiseq><placeholder-1/" -"><placeholder-2/></guiseq> menu." +#. Put one translator per line, in the form of NAME <EMAIL>, YEAR1, YEAR2 +#: /home/bob/bzr/simple-scan/help/C/legal.xml:0(None) +msgid "translator-credits" msgstr "" -"Standardmäßig werden beide Seiten des Papiers eingescannt, sofern Ihr Scanner " -"dies unterstützt. Einseitiges Scannen kann über das Menü " -"<guiseq><placeholder-1/><placeholder-2/></guiseq> konfiguriert werden." + diff --git a/help/de/dpi.page b/help/de/dpi.page index e0f14b1..2168252 100644 --- a/help/de/dpi.page +++ b/help/de/dpi.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#acquire"/> </info> - <title>Festlegen der Auflösung</title> + <title>Setting the Scan Resolution</title> <p> By default text documents will be scanned at 200 dots per inch (dpi) and photos at 400 dpi. diff --git a/help/de/email.page b/help/de/email.page index a182243..d2d5b91 100644 --- a/help/de/email.page +++ b/help/de/email.page @@ -5,12 +5,16 @@ <link type="guide" xref="index#use"/> </info> - <title>Per E-Mail versenden</title> + <title>Sending via Email</title> <p> To email the current document use the <guiseq><gui>Document</gui><gui>Email</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>E</key></keyseq>). Your email program will be opened with a new message containing the scanned document as an attachment. </p> - <p>Falls der Dokumenttyp auf Text gesetzt ist, dann wird der E-Mail-Anhang im PDF-Format versendet, anderenfalls wird für jede Seite ein separater JPEG-Anhang erzeugt.</p> - <p>In <link xref="save"/> finden Sie weitere Informationen über Dateiformate.</p> + <p> + If the document type is set to text the email will have a PDF attachment otherwise the email will have a JPEG attachment for each page. + </p> + <p> + See <link xref="save"/> for more information about file formats. + </p> </page> diff --git a/help/de/index.page b/help/de/index.page index 9ccc1ca..474c9cb 100644 --- a/help/de/index.page +++ b/help/de/index.page @@ -9,17 +9,17 @@ <include xmlns="http://www.w3.org/2001/XInclude" href="legal.xml"/> </info> - <title>Hilfe zu Simple Scan</title> + <title>Simple Scan Help</title> <section id="acquire" style="2column"> - <title>Scannen von Seiten</title> + <title>Scanning Pages</title> </section> <section id="modify" style="2column"> - <title>Bearbeiten des Dokuments</title> + <title>Modifying the Document</title> </section> <section id="use" style="2column"> - <title>Das Dokument verwenden</title> + <title>Using the Document</title> </section> </page> diff --git a/help/de/print.page b/help/de/print.page index 1d93167..544804c 100644 --- a/help/de/print.page +++ b/help/de/print.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#use"/> </info> - <title>Drucken</title> + <title>Printing</title> <p> To print the current document use the <guiseq><gui>Document</gui><gui>Print</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>P</key></keyseq>). diff --git a/help/de/reorder.page b/help/de/reorder.page index 9963860..0a5b80e 100644 --- a/help/de/reorder.page +++ b/help/de/reorder.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#modify"/> </info> - <title>Seiten neu anordnen</title> + <title>Reordering Pages</title> <p> To move a page, select it and move the page left or right using the <key><</key> and <key>></key> keys. diff --git a/help/de/rotate.page b/help/de/rotate.page index 6b8a65d..3ca035e 100644 --- a/help/de/rotate.page +++ b/help/de/rotate.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#modify"/> </info> - <title>Seiten drehen</title> + <title>Rotating Pages</title> <p> To rotate a page use the rotation buttons in the toolbar or the <key>[</key> and <key>]</key> keys. diff --git a/help/de/save.page b/help/de/save.page index ab8e6a3..648453d 100644 --- a/help/de/save.page +++ b/help/de/save.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#use"/> </info> - <title>Speichern in einer Datei</title> + <title>Saving to a File</title> <p> To save the current document to a file use the <guiseq><gui>Document</gui><gui>Save</gui></guiseq> menu (<keyseq><key>Ctrl</key><key>S</key></keyseq>). @@ -14,18 +14,18 @@ <terms> <item> <title>Portable Document Format (PDF)</title> - <p>Ein PDF kann mehrere Seiten enthalten (wie ein Buch) und lässt sich auf einfache Art und Weise an Andere weitergeben. Die meisten Benutzer verfügen nicht über Software zum Bearbeiten von PDF-Dokumenten, so dass sich dieses Format bestens zur Archivierung eignet.</p> - <p>Verwenden Sie diesen Typ, wenn Sie mehrere Textseiten eingescannt haben.</p> + <p>A PDF can contain multiple pages (like a book) and is easy to distribute to other people. Most people do not have software to modify PDF documents so this format is best used for archiving.</p> + <p>Use this type if you have scanned multiple pages of text.</p> </item> <item> <title>JPEG</title> - <p>JPEG ist das von Digitalkameras verwendete Dateiformat. Es ist recht klein und bestens für die Weitergabe geeignet. Die meisten Benutzer verfügen über Software zum Bearbeiten von JPEG-Fotos, außerdem lässt es sich einfach auf Webseiten sozialer Netzwerke hochladen. Falls Sie mehrere Seiten eingescannt haben, wird für jede Seite eine JPEG-Datei erzeugt.</p> - <p>Verwenden Sie diesen Typ, wenn Sie die eingescannten Bilder bearbeiten oder hochladen wollen.</p> + <p>JPEG file is the file format used by digital cameras and is very small and so easy to distribute. Most people have software to modify JPEG photos and this format is suitable for uploading to social networking sites. If you have scanned multiple pages then a JPEG file will be written for each page.</p> + <p>Use this type if you want to modify or upload the scanned images.</p> </item> <item> <title>PNG</title> - <p>PNG-Dateien enthalten die Rohdaten aus dem Scanner. Dadurch sind sie wesentlich größer als JPEG-Dateien und für die Weitergabe ungeeignet. Wenn Sie mehrere Seiten einscannen, wird für jede Seite eine PNG-Datei erzeugt.</p> - <p>Verwenden Sie diesen Typ, wenn sie hochauflösende Dateien zur Weiterverarbeitung benötigen.</p> + <p>PNG files contain the raw data from the scanner. This makes them much larger than JPEG files and not suitable for distributing. If you have scanned multiple pages then a PNG file will be written for each page.</p> + <p>Use this type if you need high resolution files for editing</p> </item> </terms> </page> diff --git a/help/de/scanner.page b/help/de/scanner.page index dc6764b..cfda8d8 100644 --- a/help/de/scanner.page +++ b/help/de/scanner.page @@ -5,7 +5,7 @@ <link type="guide" xref="index#acquire"/> </info> - <title>Einen Scanner auswählen</title> + <title>Selecting a Scanner</title> <p> If you have multiple scanners you can change which scanner is selected from the <guiseq><gui>Document</gui><gui>Preferences</gui></guiseq> menu. diff --git a/help/de/scanning.page b/help/de/scanning.page index 601c818..c91c49e 100644 --- a/help/de/scanning.page +++ b/help/de/scanning.page @@ -6,12 +6,16 @@ <link type="guide" xref="index#acquire"/> </info> - <title>Scannen einer Seite</title> + <title>Scanning a Page</title> - <p>So scannen Sie ein Dokument mit ihrem Scanner ein:</p> + <p> + To scan a document from your scanner: + </p> <steps> <item> - <p>Schließen Sie den Scanner an Ihren Rechner an.</p> + <p> + Connect the scanner to your computer. + </p> </item> <item> <p> @@ -25,7 +29,9 @@ </item> </steps> - <p>Jede Seite wird so angezeigt, wie sie gescannt wurde.</p> + <p> + The page will be shown as it is scanned. + </p> <p> Each page you scan is added to the end of your document. To start a new document select <guiseq><gui>Document</gui><gui>New</gui></guiseq>. diff --git a/po/POTFILES.in b/po/POTFILES.in index 5b62b1c..93a99e0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -3,7 +3,11 @@ [encoding: UTF-8] [type: gettext/glade]data/simple-scan.ui data/simple-scan.desktop.in -data/simple-scan.schemas.in -src/scanner.c -src/simple-scan.c -src/ui.c +data/org.gnome.SimpleScan.gschema.xml.in +src/book.vala +src/book-view.vala +src/page.vala +src/page-view.vala +src/scanner.vala +src/simple-scan.vala +src/ui.vala diff --git a/po/POTFILES.skip b/po/POTFILES.skip new file mode 100644 index 0000000..6c210b4 --- /dev/null +++ b/po/POTFILES.skip @@ -0,0 +1,7 @@ +src/book.c +src/book-view.c +src/page.c +src/page-view.c +src/scanner.c +src/simple-scan.c +src/ui.c diff --git a/src/Makefile.am b/src/Makefile.am index 8a4f587..3fa8558 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,22 +1,31 @@ bin_PROGRAMS = simple-scan simple_scan_SOURCES = \ - book.c \ - book.h \ - book-view.c \ - book-view.h \ - page.c \ - page.h \ - page-view.c \ - page-view.h \ - simple-scan.c \ - scanner.c \ - scanner.h \ - ui.c \ - ui.h + config.vapi \ + book.vala \ + book-view.vala \ + colord.vapi \ + jpeglib.vapi \ + page.vala \ + page-view.vala \ + sane.vapi \ + simple-scan.vala \ + scanner.vala \ + ui.vala + +simple_scan_VALAFLAGS = \ + --pkg=zlib \ + --pkg=gudev-1.0 \ + --pkg=gio-2.0 \ + --pkg=gtk+-3.0 + +if HAVE_COLORD +simple_scan_VALAFLAGS += -D HAVE_COLORD +endif simple_scan_CFLAGS = \ $(SIMPLE_SCAN_CFLAGS) \ + $(COLORD_CFLAGS) \ $(WARN_CFLAGS) \ -DVERSION=\"$(VERSION)\" \ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ @@ -28,9 +37,14 @@ simple_scan_CFLAGS = \ simple_scan_LDADD = \ $(SIMPLE_SCAN_LIBS) \ + $(COLORD_LIBS) \ -lsane \ -ljpeg \ -lm +CLEANFILES = \ + $(patsubst %.vala,%.c,$(filter %.vala, $(SOURCES))) \ + *_vala.stamp + DISTCLEANFILES = \ Makefile.in diff --git a/src/Makefile.in b/src/Makefile.in index 946fc6c..33521bc 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -33,13 +33,17 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = simple-scan$(EXEEXT) +@HAVE_COLORD_TRUE@am__append_1 = -D HAVE_COLORD subdir = src -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in book-view.c \ + book.c page-view.c page.c scanner.c simple-scan.c \ + simple_scan_vala.stamp ui.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" @@ -51,10 +55,10 @@ am_simple_scan_OBJECTS = simple_scan-book.$(OBJEXT) \ simple_scan-scanner.$(OBJEXT) simple_scan-ui.$(OBJEXT) simple_scan_OBJECTS = $(am_simple_scan_OBJECTS) am__DEPENDENCIES_1 = -simple_scan_DEPENDENCIES = $(am__DEPENDENCIES_1) +simple_scan_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) simple_scan_LINK = $(CCLD) $(simple_scan_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -74,6 +78,10 @@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_$(V)) am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) am__v_CCLD_0 = @echo " CCLD " $@; +VALACOMPILE = $(VALAC) $(AM_VALAFLAGS) $(VALAFLAGS) +AM_V_VALAC = $(am__v_VALAC_$(V)) +am__v_VALAC_ = $(am__v_VALAC_$(AM_DEFAULT_VERBOSITY)) +am__v_VALAC_0 = @echo " VALAC " $@; AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; @@ -93,6 +101,8 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +COLORD_CFLAGS = @COLORD_CFLAGS@ +COLORD_LIBS = @COLORD_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -107,11 +117,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ HELP_DIR = @HELP_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -151,6 +161,7 @@ SIMPLE_SCAN_CFLAGS = @SIMPLE_SCAN_CFLAGS@ SIMPLE_SCAN_LIBS = @SIMPLE_SCAN_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ +VALAC = @VALAC@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -172,6 +183,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ @@ -197,22 +209,23 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ simple_scan_SOURCES = \ - book.c \ - book.h \ - book-view.c \ - book-view.h \ - page.c \ - page.h \ - page-view.c \ - page-view.h \ - simple-scan.c \ - scanner.c \ - scanner.h \ - ui.c \ - ui.h - + config.vapi \ + book.vala \ + book-view.vala \ + colord.vapi \ + jpeglib.vapi \ + page.vala \ + page-view.vala \ + sane.vapi \ + simple-scan.vala \ + scanner.vala \ + ui.vala + +simple_scan_VALAFLAGS = --pkg=zlib --pkg=gudev-1.0 --pkg=gio-2.0 \ + --pkg=gtk+-3.0 $(am__append_1) simple_scan_CFLAGS = \ $(SIMPLE_SCAN_CFLAGS) \ + $(COLORD_CFLAGS) \ $(WARN_CFLAGS) \ -DVERSION=\"$(VERSION)\" \ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ @@ -224,10 +237,15 @@ simple_scan_CFLAGS = \ simple_scan_LDADD = \ $(SIMPLE_SCAN_LIBS) \ + $(COLORD_LIBS) \ -lsane \ -ljpeg \ -lm +CLEANFILES = \ + $(patsubst %.vala,%.c,$(filter %.vala, $(SOURCES))) \ + *_vala.stamp + DISTCLEANFILES = \ Makefile.in @@ -447,6 +465,44 @@ simple_scan-ui.obj: ui.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ui.c' object='simple_scan-ui.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(simple_scan_CFLAGS) $(CFLAGS) -c -o simple_scan-ui.obj `if test -f 'ui.c'; then $(CYGPATH_W) 'ui.c'; else $(CYGPATH_W) '$(srcdir)/ui.c'; fi` +$(srcdir)/book.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +$(srcdir)/book-view.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +$(srcdir)/page.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +$(srcdir)/page-view.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +$(srcdir)/simple-scan.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +$(srcdir)/scanner.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +$(srcdir)/ui.c: $(srcdir)/simple_scan_vala.stamp + @if test -f $@; then :; else \ + rm -f $(srcdir)/simple_scan_vala.stamp; \ + $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \ + fi +simple_scan_vala.stamp: $(simple_scan_SOURCES) + $(AM_V_VALAC)$(VALAC) $(simple_scan_VALAFLAGS) $(VALAFLAGS) -C $(simple_scan_SOURCES) + $(AM_V_at)touch $@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -554,6 +610,7 @@ install-strip: mostlyclean-generic: clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -563,6 +620,14 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." + -rm -f book-view.c + -rm -f book.c + -rm -f page-view.c + -rm -f page.c + -rm -f scanner.c + -rm -f simple-scan.c + -rm -f simple_scan_vala.stamp + -rm -f ui.c clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am diff --git a/src/book-view.c b/src/book-view.c index ac6e32c..5d2e84d 100644 --- a/src/book-view.c +++ b/src/book-view.c @@ -1,806 +1,1554 @@ +/* book-view.c generated by valac 0.13.1, the Vala compiler + * generated from book-view.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. See http://www.gnu.org/copyleft/gpl.html the full text of the * license. */ +/* FIXME: When scrolling, copy existing render sideways?*/ +/* FIXME: Only render pages that change and only the part that changed*/ + +#include <glib.h> +#include <glib-object.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <cairo.h> +#include <float.h> +#include <math.h> + + +#define TYPE_BOOK_VIEW (book_view_get_type ()) +#define BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK_VIEW, BookView)) +#define BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK_VIEW, BookViewClass)) +#define IS_BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK_VIEW)) +#define IS_BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK_VIEW)) +#define BOOK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK_VIEW, BookViewClass)) + +typedef struct _BookView BookView; +typedef struct _BookViewClass BookViewClass; +typedef struct _BookViewPrivate BookViewPrivate; + +#define TYPE_BOOK (book_get_type ()) +#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book)) +#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass)) +#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK)) +#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK)) +#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass)) + +typedef struct _Book Book; +typedef struct _BookClass BookClass; + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; + +#define TYPE_PAGE_VIEW (page_view_get_type ()) +#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE_VIEW, PageView)) +#define PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE_VIEW, PageViewClass)) +#define IS_PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE_VIEW)) +#define IS_PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE_VIEW)) +#define PAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE_VIEW, PageViewClass)) + +typedef struct _PageView PageView; +typedef struct _PageViewClass PageViewClass; +#define _book_unref0(var) ((var == NULL) ? NULL : (var = (book_unref (var), NULL))) +#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL))) +#define _page_view_unref0(var) ((var == NULL) ? NULL : (var = (page_view_unref (var), NULL))) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL))) + +struct _BookView { + GtkVBox parent_instance; + BookViewPrivate * priv; +}; -#include <gdk/gdkkeysyms.h> +struct _BookViewClass { + GtkVBoxClass parent_class; +}; -#include "book-view.h" -#include "page-view.h" +struct _BookViewPrivate { + Book* book; + GHashTable* page_data; + gboolean need_layout; + gboolean laying_out; + gboolean show_selected_page; + PageView* selected_page; + GtkWidget* drawing_area; + GtkHScrollbar* scroll; + GtkAdjustment* adjustment; + GdkCursorType cursor; +}; -// FIXME: When scrolling, copy existing render sideways? -// FIXME: Only render pages that change and only the part that changed -enum { - PROP_0, - PROP_BOOK +static gpointer book_view_parent_class = NULL; + +GType book_view_get_type (void) G_GNUC_CONST; +gpointer book_ref (gpointer instance); +void book_unref (gpointer instance); +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_book (GValue* value, gpointer v_object); +void value_take_book (GValue* value, gpointer v_object); +gpointer value_get_book (const GValue* value); +GType book_get_type (void) G_GNUC_CONST; +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +gpointer page_view_ref (gpointer instance); +void page_view_unref (gpointer instance); +GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page_view (GValue* value, gpointer v_object); +void value_take_page_view (GValue* value, gpointer v_object); +gpointer value_get_page_view (const GValue* value); +GType page_view_get_type (void) G_GNUC_CONST; +#define BOOK_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_BOOK_VIEW, BookViewPrivate)) +enum { + BOOK_VIEW_DUMMY_PROPERTY }; +BookView* book_view_new (Book* book); +BookView* book_view_construct (GType object_type, Book* book); +guint book_get_n_pages (Book* self); +Page* book_get_page (Book* self, gint page_number); +static void book_view_add_cb (BookView* self, Book* book, Page* page); +void book_view_select_page (BookView* self, Page* page); +static void _book_view_add_cb_book_page_added (Book* _sender, Page* page, gpointer self); +static void book_view_remove_cb (BookView* self, Book* book, Page* page); +static void _book_view_remove_cb_book_page_removed (Book* _sender, Page* page, gpointer self); +static void book_view_reorder_cb (BookView* self, Book* book); +static void _book_view_reorder_cb_book_reordered (Book* _sender, gpointer self); +static void book_view_clear_cb (BookView* self, Book* book); +static void _book_view_clear_cb_book_cleared (Book* _sender, gpointer self); +static void _page_unref0_ (gpointer var); +static void _page_view_unref0_ (gpointer var); +static gboolean book_view_configure_cb (BookView* self, GtkWidget* widget, GdkEventConfigure* event); +static gboolean _book_view_configure_cb_gtk_widget_configure_event (GtkWidget* _sender, GdkEventConfigure* event, gpointer self); +static gboolean book_view_draw_cb (BookView* self, GtkWidget* widget, cairo_t* context); +static gboolean _book_view_draw_cb_gtk_widget_draw (GtkWidget* _sender, cairo_t* cr, gpointer self); +static gboolean book_view_motion_cb (BookView* self, GtkWidget* widget, GdkEventMotion* event); +static gboolean _book_view_motion_cb_gtk_widget_motion_notify_event (GtkWidget* _sender, GdkEventMotion* event, gpointer self); +static gboolean book_view_key_cb (BookView* self, GtkWidget* widget, GdkEventKey* event); +static gboolean _book_view_key_cb_gtk_widget_key_press_event (GtkWidget* _sender, GdkEventKey* event, gpointer self); +static gboolean book_view_button_cb (BookView* self, GtkWidget* widget, GdkEventButton* event); +static gboolean _book_view_button_cb_gtk_widget_button_press_event (GtkWidget* _sender, GdkEventButton* event, gpointer self); +static gboolean _book_view_button_cb_gtk_widget_button_release_event (GtkWidget* _sender, GdkEventButton* event, gpointer self); +static gboolean book_view_focus_cb (BookView* self, GtkWidget* widget, GdkEventFocus* event); +static gboolean _book_view_focus_cb_gtk_widget_focus_in_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self); +static gboolean _book_view_focus_cb_gtk_widget_focus_out_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self); +static void book_view_scroll_cb (BookView* self, GtkAdjustment* adjustment); +static void _book_view_scroll_cb_gtk_adjustment_value_changed (GtkAdjustment* _sender, gpointer self); +static PageView* book_view_get_nth_page (BookView* self, gint n); +static PageView* book_view_get_next_page (BookView* self, PageView* page); +Page* page_view_get_page (PageView* self); +static PageView* book_view_get_prev_page (BookView* self, PageView* page); +static void book_view_page_view_changed_cb (BookView* self, PageView* page); +void book_view_redraw (BookView* self); +static void book_view_page_view_size_changed_cb (BookView* self, PageView* page); +PageView* page_view_new (Page* page); +PageView* page_view_construct (GType object_type, Page* page); +static void _book_view_page_view_changed_cb_page_view_changed (PageView* _sender, gpointer self); +static void _book_view_page_view_size_changed_cb_page_view_size_changed (PageView* _sender, gpointer self); +static void book_view_set_selected_page (BookView* self, PageView* page); +void page_view_set_selected (PageView* self, gboolean selected); +static void book_view_set_x_offset (BookView* self, gint offset); +static gint book_view_get_x_offset (BookView* self); +static void book_view_show_page_view (BookView* self, PageView* page); +gint page_view_get_x_offset (PageView* self); +gint page_view_get_width (PageView* self); +static void book_view_select_page_view (BookView* self, PageView* page); +Page* book_view_get_selected (BookView* self); +Book* book_view_get_book (BookView* self); +static void book_view_layout_into (BookView* self, gint width, gint height, gint* book_width, gint* book_height); +gint page_get_dpi (Page* self); +gint page_get_width (Page* self); +gint page_get_height (Page* self); +void page_view_set_width (PageView* self, gint width); +void page_view_set_height (PageView* self, gint height); +gint page_view_get_height (PageView* self); +void page_view_set_x_offset (PageView* self, gint offset); +void page_view_set_y_offset (PageView* self, gint offset); +static void book_view_layout (BookView* self); +void page_view_render (PageView* self, cairo_t* context); +gboolean page_view_get_selected (PageView* self); +gint page_view_get_y_offset (PageView* self); +static PageView* book_view_get_page_at (BookView* self, gint x, gint y, gint* x_, gint* y_); +void page_view_button_press (PageView* self, gint x, gint y); +void page_view_button_release (PageView* self, gint x, gint y); +static void book_view_set_cursor (BookView* self, GdkCursorType cursor); +void page_view_motion (PageView* self, gint x, gint y); +GdkCursorType page_view_get_cursor (PageView* self); +void book_view_select_next_page (BookView* self); +void book_view_select_prev_page (BookView* self); +static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void book_view_finalize (GObject* obj); + + +static gpointer _book_ref0 (gpointer self) { + return self ? book_ref (self) : NULL; +} + + +static void _book_view_add_cb_book_page_added (Book* _sender, Page* page, gpointer self) { + book_view_add_cb (self, _sender, page); +} + + +static void _book_view_remove_cb_book_page_removed (Book* _sender, Page* page, gpointer self) { + book_view_remove_cb (self, _sender, page); +} + + +static void _book_view_reorder_cb_book_reordered (Book* _sender, gpointer self) { + book_view_reorder_cb (self, _sender); +} + + +static void _book_view_clear_cb_book_cleared (Book* _sender, gpointer self) { + book_view_clear_cb (self, _sender); +} + + +static void _page_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (page_unref (var), NULL)); +} + + +static void _page_view_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (page_view_unref (var), NULL)); +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +static gboolean _book_view_configure_cb_gtk_widget_configure_event (GtkWidget* _sender, GdkEventConfigure* event, gpointer self) { + gboolean result; + result = book_view_configure_cb (self, _sender, event); + return result; +} -enum { - PAGE_SELECTED, - SHOW_PAGE, - SHOW_MENU, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0, }; - -struct BookViewPrivate -{ - /* Book being rendered */ - Book *book; - GHashTable *page_data; - - /* True if the view needs to be laid out again */ - gboolean need_layout, laying_out, show_selected_page; - - /* Currently selected page */ - PageView *selected_page; - - /* Widget being rendered to */ - GtkWidget *drawing_area; - - /* Horizontal scrollbar */ - GtkWidget *scroll; - GtkAdjustment *adjustment; - - gint cursor; -}; -G_DEFINE_TYPE (BookView, book_view, GTK_TYPE_VBOX); +static gboolean _book_view_draw_cb_gtk_widget_draw (GtkWidget* _sender, cairo_t* cr, gpointer self) { + gboolean result; + result = book_view_draw_cb (self, _sender, cr); + return result; +} -BookView * -book_view_new (Book *book) -{ - return g_object_new (BOOK_VIEW_TYPE, "book", book, NULL); +static gboolean _book_view_motion_cb_gtk_widget_motion_notify_event (GtkWidget* _sender, GdkEventMotion* event, gpointer self) { + gboolean result; + result = book_view_motion_cb (self, _sender, event); + return result; } -static PageView * -get_nth_page (BookView *view, gint n) -{ - Page *page = book_get_page (view->priv->book, n); - return g_hash_table_lookup (view->priv->page_data, page); +static gboolean _book_view_key_cb_gtk_widget_key_press_event (GtkWidget* _sender, GdkEventKey* event, gpointer self) { + gboolean result; + result = book_view_key_cb (self, _sender, event); + return result; } -static PageView * -get_next_page (BookView *view, PageView *page) -{ - gint i; - - for (i = 0; ; i++) { - Page *p; - p = book_get_page (view->priv->book, i); - if (!p) - break; - if (p == page_view_get_page (page)) { - p = book_get_page (view->priv->book, i + 1); - if (p) - return g_hash_table_lookup (view->priv->page_data, p); - } - } - - return page; +static gboolean _book_view_button_cb_gtk_widget_button_press_event (GtkWidget* _sender, GdkEventButton* event, gpointer self) { + gboolean result; + result = book_view_button_cb (self, _sender, event); + return result; } -static PageView * -get_prev_page (BookView *view, PageView *page) -{ - gint i; - PageView *prev_page = page; +static gboolean _book_view_button_cb_gtk_widget_button_release_event (GtkWidget* _sender, GdkEventButton* event, gpointer self) { + gboolean result; + result = book_view_button_cb (self, _sender, event); + return result; +} - for (i = 0; ; i++) { - Page *p; - p = book_get_page (view->priv->book, i); - if (!p) - break; - if (p == page_view_get_page (page)) - return prev_page; - prev_page = g_hash_table_lookup (view->priv->page_data, p); - } - return page; +static gboolean _book_view_focus_cb_gtk_widget_focus_in_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self) { + gboolean result; + result = book_view_focus_cb (self, _sender, event); + return result; } -static void -page_view_changed_cb (PageView *page, BookView *view) -{ - book_view_redraw (view); +static gboolean _book_view_focus_cb_gtk_widget_focus_out_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self) { + gboolean result; + result = book_view_focus_cb (self, _sender, event); + return result; } -static void -page_view_size_changed_cb (PageView *page, BookView *view) -{ - view->priv->need_layout = TRUE; - book_view_redraw (view); +static void _book_view_scroll_cb_gtk_adjustment_value_changed (GtkAdjustment* _sender, gpointer self) { + book_view_scroll_cb (self, _sender); } -static void -add_cb (Book *book, Page *page, BookView *view) -{ - PageView *page_view; - page_view = page_view_new (page); - g_signal_connect (page_view, "changed", G_CALLBACK (page_view_changed_cb), view); - g_signal_connect (page_view, "size-changed", G_CALLBACK (page_view_size_changed_cb), view); - g_hash_table_insert (view->priv->page_data, page, page_view); - view->priv->need_layout = TRUE; - book_view_redraw (view); +BookView* book_view_construct (GType object_type, Book* book) { + BookView * self = NULL; + Book* _tmp0_; + Page* _tmp4_ = NULL; + Page* _tmp5_; + GHashTable* _tmp6_ = NULL; + GtkDrawingArea* _tmp7_ = NULL; + GtkHScrollbar* _tmp8_ = NULL; + GtkAdjustment* _tmp9_ = NULL; + GtkAdjustment* _tmp10_; + g_return_val_if_fail (book != NULL, NULL); + self = (BookView*) g_object_new (object_type, NULL); + _tmp0_ = _book_ref0 (book); + _book_unref0 (self->priv->book); + self->priv->book = _tmp0_; + { + gint i; + i = 0; + { + gboolean _tmp1_; + _tmp1_ = TRUE; + while (TRUE) { + guint _tmp2_; + Page* _tmp3_ = NULL; + Page* page; + if (!_tmp1_) { + i++; + } + _tmp1_ = FALSE; + _tmp2_ = book_get_n_pages (book); + if (!(((guint) i) < _tmp2_)) { + break; + } + _tmp3_ = book_get_page (book, i); + page = _tmp3_; + book_view_add_cb (self, book, page); + _page_unref0 (page); + } + } + } + _tmp4_ = book_get_page (book, 0); + _tmp5_ = _tmp4_; + book_view_select_page (self, _tmp5_); + _page_unref0 (_tmp5_); + g_signal_connect_object (book, "page-added", (GCallback) _book_view_add_cb_book_page_added, self, 0); + g_signal_connect_object (book, "page-removed", (GCallback) _book_view_remove_cb_book_page_removed, self, 0); + g_signal_connect_object (book, "reordered", (GCallback) _book_view_reorder_cb_book_reordered, self, 0); + g_signal_connect_object (book, "cleared", (GCallback) _book_view_clear_cb_book_cleared, self, 0); + self->priv->need_layout = TRUE; + _tmp6_ = g_hash_table_new_full (g_direct_hash, g_direct_equal, _page_unref0_, _page_view_unref0_); + _g_hash_table_unref0 (self->priv->page_data); + self->priv->page_data = _tmp6_; + self->priv->cursor = GDK_ARROW; + _tmp7_ = (GtkDrawingArea*) gtk_drawing_area_new (); + _g_object_unref0 (self->priv->drawing_area); + self->priv->drawing_area = (GtkWidget*) g_object_ref_sink (_tmp7_); + gtk_widget_set_size_request (self->priv->drawing_area, 200, 100); + gtk_widget_set_can_focus (self->priv->drawing_area, TRUE); + gtk_widget_set_events (self->priv->drawing_area, (gint) (((((GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK) | GDK_BUTTON_RELEASE_MASK) | GDK_FOCUS_CHANGE_MASK) | GDK_STRUCTURE_MASK) | GDK_SCROLL_MASK)); + gtk_box_pack_start ((GtkBox*) self, self->priv->drawing_area, TRUE, TRUE, (guint) 0); + _tmp8_ = (GtkHScrollbar*) gtk_hscrollbar_new (NULL); + _g_object_unref0 (self->priv->scroll); + self->priv->scroll = g_object_ref_sink (_tmp8_); + _tmp9_ = gtk_range_get_adjustment ((GtkRange*) self->priv->scroll); + _tmp10_ = _g_object_ref0 (_tmp9_); + _g_object_unref0 (self->priv->adjustment); + self->priv->adjustment = _tmp10_; + gtk_box_pack_start ((GtkBox*) self, (GtkWidget*) self->priv->scroll, FALSE, TRUE, (guint) 0); + g_signal_connect_object (self->priv->drawing_area, "configure-event", (GCallback) _book_view_configure_cb_gtk_widget_configure_event, self, 0); + g_signal_connect_object (self->priv->drawing_area, "draw", (GCallback) _book_view_draw_cb_gtk_widget_draw, self, 0); + g_signal_connect_object (self->priv->drawing_area, "motion-notify-event", (GCallback) _book_view_motion_cb_gtk_widget_motion_notify_event, self, 0); + g_signal_connect_object (self->priv->drawing_area, "key-press-event", (GCallback) _book_view_key_cb_gtk_widget_key_press_event, self, 0); + g_signal_connect_object (self->priv->drawing_area, "button-press-event", (GCallback) _book_view_button_cb_gtk_widget_button_press_event, self, 0); + g_signal_connect_object (self->priv->drawing_area, "button-release-event", (GCallback) _book_view_button_cb_gtk_widget_button_release_event, self, 0); + g_signal_connect_object (self->priv->drawing_area, "focus-in-event", (GCallback) _book_view_focus_cb_gtk_widget_focus_in_event, self, G_CONNECT_AFTER); + g_signal_connect_object (self->priv->drawing_area, "focus-out-event", (GCallback) _book_view_focus_cb_gtk_widget_focus_out_event, self, G_CONNECT_AFTER); + g_signal_connect_object (self->priv->adjustment, "value-changed", (GCallback) _book_view_scroll_cb_gtk_adjustment_value_changed, self, 0); + gtk_widget_show (self->priv->drawing_area); + return self; } -static void -set_selected_page (BookView *view, PageView *page) -{ - /* Deselect existing page if changed */ - if (view->priv->selected_page && page != view->priv->selected_page) - page_view_set_selected (view->priv->selected_page, FALSE); +BookView* book_view_new (Book* book) { + return book_view_construct (TYPE_BOOK_VIEW, book); +} - view->priv->selected_page = page; - if (!view->priv->selected_page) - return; - /* Select new page if widget has focus */ - if (!gtk_widget_has_focus (view->priv->drawing_area)) - page_view_set_selected (view->priv->selected_page, FALSE); - else - page_view_set_selected (view->priv->selected_page, TRUE); +static gpointer _page_view_ref0 (gpointer self) { + return self ? page_view_ref (self) : NULL; } -static void -set_x_offset (BookView *view, gint offset) -{ - gtk_adjustment_set_value (view->priv->adjustment, offset); +static PageView* book_view_get_nth_page (BookView* self, gint n) { + PageView* result = NULL; + Page* _tmp0_ = NULL; + Page* page; + gconstpointer _tmp1_ = NULL; + PageView* _tmp2_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = book_get_page (self->priv->book, n); + page = _tmp0_; + _tmp1_ = g_hash_table_lookup (self->priv->page_data, page); + _tmp2_ = _page_view_ref0 ((PageView*) _tmp1_); + result = _tmp2_; + _page_unref0 (page); + return result; } -static gint -get_x_offset (BookView *view) -{ - return (gint) gtk_adjustment_get_value (view->priv->adjustment); +static PageView* book_view_get_next_page (BookView* self, PageView* page) { + PageView* result = NULL; + PageView* _tmp8_; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (page != NULL, NULL); + { + gint i; + i = 0; + { + gboolean _tmp0_; + _tmp0_ = TRUE; + while (TRUE) { + Page* _tmp1_ = NULL; + Page* p; + Page* _tmp2_ = NULL; + Page* _tmp3_; + gboolean _tmp4_; + if (!_tmp0_) { + i++; + } + _tmp0_ = FALSE; + _tmp1_ = book_get_page (self->priv->book, i); + p = _tmp1_; + if (p == NULL) { + _page_unref0 (p); + break; + } + _tmp2_ = page_view_get_page (page); + _tmp3_ = _tmp2_; + _tmp4_ = p == _tmp3_; + _page_unref0 (_tmp3_); + if (_tmp4_) { + Page* _tmp5_ = NULL; + _tmp5_ = book_get_page (self->priv->book, i + 1); + _page_unref0 (p); + p = _tmp5_; + if (p != NULL) { + gconstpointer _tmp6_ = NULL; + PageView* _tmp7_; + _tmp6_ = g_hash_table_lookup (self->priv->page_data, p); + _tmp7_ = _page_view_ref0 ((PageView*) _tmp6_); + result = _tmp7_; + _page_unref0 (p); + return result; + } + } + _page_unref0 (p); + } + } + } + _tmp8_ = _page_view_ref0 (page); + result = _tmp8_; + return result; } -static void -show_page (BookView *view, PageView *page) -{ - gint left_edge, right_edge; - GtkAllocation allocation; +static PageView* book_view_get_prev_page (BookView* self, PageView* page) { + PageView* result = NULL; + PageView* _tmp0_; + PageView* prev_page; + PageView* _tmp8_; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (page != NULL, NULL); + _tmp0_ = _page_view_ref0 (page); + prev_page = _tmp0_; + { + gint i; + i = 0; + { + gboolean _tmp1_; + _tmp1_ = TRUE; + while (TRUE) { + Page* _tmp2_ = NULL; + Page* p; + Page* _tmp3_ = NULL; + Page* _tmp4_; + gboolean _tmp5_; + gconstpointer _tmp6_ = NULL; + PageView* _tmp7_; + if (!_tmp1_) { + i++; + } + _tmp1_ = FALSE; + _tmp2_ = book_get_page (self->priv->book, i); + p = _tmp2_; + if (p == NULL) { + _page_unref0 (p); + break; + } + _tmp3_ = page_view_get_page (page); + _tmp4_ = _tmp3_; + _tmp5_ = p == _tmp4_; + _page_unref0 (_tmp4_); + if (_tmp5_) { + result = prev_page; + _page_unref0 (p); + return result; + } + _tmp6_ = g_hash_table_lookup (self->priv->page_data, p); + _tmp7_ = _page_view_ref0 ((PageView*) _tmp6_); + _page_view_unref0 (prev_page); + prev_page = _tmp7_; + _page_unref0 (p); + } + } + } + _tmp8_ = _page_view_ref0 (page); + result = _tmp8_; + _page_view_unref0 (prev_page); + return result; +} + - if (!page || !gtk_widget_get_visible (view->priv->scroll)) - return; +static void book_view_page_view_changed_cb (BookView* self, PageView* page) { + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + book_view_redraw (self); +} - gtk_widget_get_allocation(view->priv->drawing_area, &allocation); - left_edge = page_view_get_x_offset (page); - right_edge = page_view_get_x_offset (page) + page_view_get_width (page); - if (left_edge - get_x_offset (view) < 0) - set_x_offset(view, left_edge); - else if (right_edge - get_x_offset (view) > allocation.width) - set_x_offset(view, right_edge - allocation.width); +static void book_view_page_view_size_changed_cb (BookView* self, PageView* page) { + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + self->priv->need_layout = TRUE; + book_view_redraw (self); } -static void -select_page (BookView *view, PageView *page) -{ - Page *p = NULL; - - if (view->priv->selected_page == page) - return; +static void _book_view_page_view_changed_cb_page_view_changed (PageView* _sender, gpointer self) { + book_view_page_view_changed_cb (self, _sender); +} + - set_selected_page (view, page); +static void _book_view_page_view_size_changed_cb_page_view_size_changed (PageView* _sender, gpointer self) { + book_view_page_view_size_changed_cb (self, _sender); +} - if (view->priv->need_layout) - view->priv->show_selected_page = TRUE; - else - show_page (view, page); - if (page) - p = page_view_get_page (page); - g_signal_emit (view, signals[PAGE_SELECTED], 0, p); +static gpointer _page_ref0 (gpointer self) { + return self ? page_ref (self) : NULL; } -static void -remove_cb (Book *book, Page *page, BookView *view) -{ - PageView *new_selection = view->priv->selected_page; +static void book_view_add_cb (BookView* self, Book* book, Page* page) { + PageView* _tmp0_ = NULL; + PageView* page_view; + Page* _tmp1_; + PageView* _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = page_view_new (page); + page_view = _tmp0_; + g_signal_connect_object (page_view, "changed", (GCallback) _book_view_page_view_changed_cb_page_view_changed, self, 0); + g_signal_connect_object (page_view, "size-changed", (GCallback) _book_view_page_view_size_changed_cb_page_view_size_changed, self, 0); + _tmp1_ = _page_ref0 (page); + _tmp2_ = _page_view_ref0 (page_view); + g_hash_table_insert (self->priv->page_data, _tmp1_, _tmp2_); + self->priv->need_layout = TRUE; + book_view_redraw (self); + _page_view_unref0 (page_view); +} - /* Select previous page or next if removing the selected page */ - if (page == book_view_get_selected (view)) { - new_selection = get_prev_page (view, view->priv->selected_page); - if (new_selection == view->priv->selected_page) - new_selection = get_next_page (view, view->priv->selected_page); - view->priv->selected_page = NULL; - } - g_hash_table_remove (view->priv->page_data, page); +static void book_view_set_selected_page (BookView* self, PageView* page) { + gboolean _tmp0_ = FALSE; + PageView* _tmp1_; + gboolean _tmp2_; + g_return_if_fail (self != NULL); + if (self->priv->selected_page != NULL) { + _tmp0_ = page != self->priv->selected_page; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + page_view_set_selected (self->priv->selected_page, FALSE); + } + _tmp1_ = _page_view_ref0 (page); + _page_view_unref0 (self->priv->selected_page); + self->priv->selected_page = _tmp1_; + if (self->priv->selected_page == NULL) { + return; + } + g_object_get (self->priv->drawing_area, "has-focus", &_tmp2_, NULL); + if (!_tmp2_) { + page_view_set_selected (self->priv->selected_page, FALSE); + } else { + page_view_set_selected (self->priv->selected_page, TRUE); + } +} - select_page (view, new_selection); - view->priv->need_layout = TRUE; - book_view_redraw (view); +static void book_view_set_x_offset (BookView* self, gint offset) { + g_return_if_fail (self != NULL); + gtk_adjustment_set_value (self->priv->adjustment, (gdouble) offset); } -static void -reorder_cb (Book *book, BookView *view) -{ - view->priv->need_layout = TRUE; - book_view_redraw (view); +static gint book_view_get_x_offset (BookView* self) { + gint result = 0; + gdouble _tmp0_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = gtk_adjustment_get_value (self->priv->adjustment); + result = (gint) _tmp0_; + return result; } -static void -clear_cb (Book *book, BookView *view) -{ - g_hash_table_remove_all (view->priv->page_data); - view->priv->selected_page = NULL; - g_signal_emit (view, signals[PAGE_SELECTED], 0, NULL); - view->priv->need_layout = TRUE; - book_view_redraw (view); +static void book_view_show_page_view (BookView* self, PageView* page) { + gboolean _tmp0_ = FALSE; + GtkAllocation allocation = {0}; + GtkAllocation _tmp2_ = {0}; + gint _tmp3_; + gint left_edge; + gint _tmp4_; + gint _tmp5_; + gint right_edge; + gint _tmp6_; + g_return_if_fail (self != NULL); + if (page == NULL) { + _tmp0_ = TRUE; + } else { + gboolean _tmp1_; + _tmp1_ = gtk_widget_get_visible ((GtkWidget*) self->priv->scroll); + _tmp0_ = !_tmp1_; + } + if (_tmp0_) { + return; + } + gtk_widget_get_allocation (self->priv->drawing_area, &_tmp2_); + allocation = _tmp2_; + _tmp3_ = page_view_get_x_offset (page); + left_edge = _tmp3_; + _tmp4_ = page_view_get_x_offset (page); + _tmp5_ = page_view_get_width (page); + right_edge = _tmp4_ + _tmp5_; + _tmp6_ = book_view_get_x_offset (self); + if ((left_edge - _tmp6_) < 0) { + book_view_set_x_offset (self, left_edge); + } else { + gint _tmp7_; + _tmp7_ = book_view_get_x_offset (self); + if ((right_edge - _tmp7_) > allocation.width) { + book_view_set_x_offset (self, right_edge - allocation.width); + } + } } -Book * -book_view_get_book (BookView *view) -{ - g_return_val_if_fail (view != NULL, NULL); +static void book_view_select_page_view (BookView* self, PageView* page) { + Page* p; + g_return_if_fail (self != NULL); + p = NULL; + if (self->priv->selected_page == page) { + _page_unref0 (p); + return; + } + book_view_set_selected_page (self, page); + if (self->priv->need_layout) { + self->priv->show_selected_page = TRUE; + } else { + book_view_show_page_view (self, page); + } + if (page != NULL) { + Page* _tmp0_ = NULL; + _tmp0_ = page_view_get_page (page); + _page_unref0 (p); + p = _tmp0_; + } + g_signal_emit_by_name (self, "page-selected", p); + _page_unref0 (p); +} + - return view->priv->book; +static void book_view_remove_cb (BookView* self, Book* book, Page* page) { + PageView* _tmp0_; + PageView* new_selection; + Page* _tmp1_ = NULL; + Page* _tmp2_; + gboolean _tmp3_; + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = _page_view_ref0 (self->priv->selected_page); + new_selection = _tmp0_; + _tmp1_ = book_view_get_selected (self); + _tmp2_ = _tmp1_; + _tmp3_ = page == _tmp2_; + _page_unref0 (_tmp2_); + if (_tmp3_) { + PageView* _tmp4_ = NULL; + _tmp4_ = book_view_get_prev_page (self, self->priv->selected_page); + _page_view_unref0 (new_selection); + new_selection = _tmp4_; + if (new_selection == self->priv->selected_page) { + PageView* _tmp5_ = NULL; + _tmp5_ = book_view_get_next_page (self, self->priv->selected_page); + _page_view_unref0 (new_selection); + new_selection = _tmp5_; + } + _page_view_unref0 (self->priv->selected_page); + self->priv->selected_page = NULL; + } + g_hash_table_remove (self->priv->page_data, page); + book_view_select_page_view (self, new_selection); + self->priv->need_layout = TRUE; + book_view_redraw (self); + _page_view_unref0 (new_selection); } -static gboolean -configure_cb (GtkWidget *widget, GdkEventConfigure *event, BookView *view) -{ - view->priv->need_layout = TRUE; - return FALSE; +static void book_view_reorder_cb (BookView* self, Book* book) { + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + self->priv->need_layout = TRUE; + book_view_redraw (self); } -static void -layout_into (BookView *view, gint width, gint height, gint *book_width, gint *book_height) -{ - gint spacing = 12; - gint max_width = 0, max_height = 0; - gdouble aspect, max_aspect; - gint x_offset = 0; - gint i, n_pages; - gint max_dpi = 0; +static void book_view_clear_cb (BookView* self, Book* book) { + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + g_hash_table_remove_all (self->priv->page_data); + _page_view_unref0 (self->priv->selected_page); + self->priv->selected_page = NULL; + g_signal_emit_by_name (self, "page-selected", NULL); + self->priv->need_layout = TRUE; + book_view_redraw (self); +} - n_pages = book_get_n_pages (view->priv->book); - /* Get maximum page resolution */ - for (i = 0; i < n_pages; i++) { - Page *page = book_get_page (view->priv->book, i); - if (page_get_dpi (page) > max_dpi) - max_dpi = page_get_dpi (page); - } +Book* book_view_get_book (BookView* self) { + Book* result = NULL; + Book* _tmp0_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = _book_ref0 (self->priv->book); + result = _tmp0_; + return result; +} - /* Get area required to fit all pages */ - for (i = 0; i < n_pages; i++) { - Page *page = book_get_page (view->priv->book, i); - gint w, h; - w = page_get_width (page); - h = page_get_height (page); +static gboolean book_view_configure_cb (BookView* self, GtkWidget* widget, GdkEventConfigure* event) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + self->priv->need_layout = TRUE; + result = FALSE; + return result; +} - /* Scale to the same DPI */ - w = (double)w * max_dpi / page_get_dpi (page) + 0.5; - h = (double)h * max_dpi / page_get_dpi (page) + 0.5; - if (w > max_width) - max_width = w; - if (h > max_height) - max_height = h; - } - - aspect = (double)width / height; - max_aspect = (double)max_width / max_height; - - /* Get total dimensions of all pages */ - *book_width = 0; - *book_height = 0; - for (i = 0; i < n_pages; i++) { - PageView *page = get_nth_page (view, i); - Page *p = page_view_get_page (page); - gint h; - - /* NOTE: Using double to avoid overflow for large images */ - if (max_aspect > aspect) { - /* Set width scaled on DPI and maximum width */ - gint w = (double)page_get_width (p) * max_dpi * width / (page_get_dpi (p) * max_width); - page_view_set_width (page, w); - } - else { - /* Set height scaled on DPI and maximum height */ - gint h = (double)page_get_height (p) * max_dpi * height / (page_get_dpi (p) * max_height); - page_view_set_height (page, h); - } - - h = page_view_get_height (page); - if (h > *book_height) - *book_height = h; - *book_width += page_view_get_width (page); - if (i != 0) - *book_width += spacing; - } - - for (i = 0; i < n_pages; i++) { - PageView *page = get_nth_page (view, i); - - /* Layout pages left to right */ - page_view_set_x_offset (page, x_offset); - x_offset += page_view_get_width (page) + spacing; - - /* Centre page vertically */ - page_view_set_y_offset (page, (height - page_view_get_height (page)) / 2); - } -} - - -static void -layout (BookView *view) -{ - gint width, height, book_width, book_height; - gboolean right_aligned = TRUE; - GtkAllocation allocation, box_allocation; - - if (!view->priv->need_layout) - return; - - view->priv->laying_out = TRUE; - - gtk_widget_get_allocation(view->priv->drawing_area, &allocation); - gtk_widget_get_allocation(GTK_WIDGET(view), &box_allocation); - - /* If scroll is right aligned then keep that after layout */ - if (gtk_adjustment_get_value (view->priv->adjustment) < gtk_adjustment_get_upper (view->priv->adjustment) - gtk_adjustment_get_page_size (view->priv->adjustment)) - right_aligned = FALSE; - - /* Try and fit without scrollbar */ - width = allocation.width; - height = box_allocation.height - gtk_container_get_border_width (GTK_CONTAINER (view)) * 2; - layout_into (view, width, height, &book_width, &book_height); - - /* Relayout with scrollbar */ - if (book_width > allocation.width) { - gint max_offset; - - /* Re-layout leaving space for scrollbar */ - height = allocation.height; - layout_into (view, width, height, &book_width, &book_height); - - /* Set scrollbar limits */ - gtk_adjustment_set_lower (view->priv->adjustment, 0); - gtk_adjustment_set_upper (view->priv->adjustment, book_width); - gtk_adjustment_set_page_size (view->priv->adjustment, allocation.width); - - /* Keep right-aligned */ - max_offset = book_width - allocation.width; - if (right_aligned || get_x_offset (view) > max_offset) - set_x_offset(view, max_offset); - - gtk_widget_show (view->priv->scroll); - } else { - gint offset; - gtk_widget_hide (view->priv->scroll); - offset = (book_width - allocation.width) / 2; - gtk_adjustment_set_lower (view->priv->adjustment, offset); - gtk_adjustment_set_upper (view->priv->adjustment, offset); - gtk_adjustment_set_page_size (view->priv->adjustment, 0); - set_x_offset(view, offset); - } - - if (view->priv->show_selected_page) - show_page (view, view->priv->selected_page); - - view->priv->need_layout = FALSE; - view->priv->show_selected_page = FALSE; - view->priv->laying_out = FALSE; -} - - -static gboolean -expose_cb (GtkWidget *widget, GdkEventExpose *event, BookView *view) -{ - gint i, n_pages; - cairo_t *context; - - n_pages = book_get_n_pages (view->priv->book); - if (n_pages == 0) - return FALSE; - - layout (view); - - context = gdk_cairo_create (gtk_widget_get_window(widget)); - - /* Render each page */ - for (i = 0; i < n_pages; i++) { - PageView *page = get_nth_page (view, i); - gint left_edge, right_edge; - - left_edge = page_view_get_x_offset (page) - get_x_offset (view); - right_edge = page_view_get_x_offset (page) + page_view_get_width (page) - get_x_offset (view); - - /* Page not visible, don't render */ - if (right_edge < event->area.x || left_edge > event->area.x + event->area.width) - continue; - - cairo_save (context); - cairo_translate (context, -get_x_offset (view), 0); - page_view_render (page, context); - cairo_restore (context); - - if (page_view_get_selected (page)) - gtk_paint_focus (gtk_widget_get_style (view->priv->drawing_area), - gtk_widget_get_window (view->priv->drawing_area), - GTK_STATE_SELECTED, - &event->area, - NULL, - NULL, - page_view_get_x_offset (page) - get_x_offset (view), - page_view_get_y_offset (page), - page_view_get_width (page), - page_view_get_height (page)); - } - - cairo_destroy (context); - - return FALSE; -} - - -static PageView * -get_page_at (BookView *view, gint x, gint y, gint *x_, gint *y_) -{ - gint i, n_pages; - - n_pages = book_get_n_pages (view->priv->book); - for (i = 0; i < n_pages; i++) { - PageView *page; - gint left, right, top, bottom; - - page = get_nth_page (view, i); - left = page_view_get_x_offset (page); - right = left + page_view_get_width (page); - top = page_view_get_y_offset (page); - bottom = top + page_view_get_height (page); - if (x >= left && x <= right && y >= top && y <= bottom) - { - *x_ = x - left; - *y_ = y - top; - return page; - } - } - - return NULL; -} - - -static gboolean -button_cb (GtkWidget *widget, GdkEventButton *event, BookView *view) -{ - gint x, y; - - layout (view); - - gtk_widget_grab_focus (view->priv->drawing_area); - - if (event->type == GDK_BUTTON_PRESS) - select_page (view, get_page_at (view, event->x + get_x_offset (view), event->y, &x, &y)); - - if (!view->priv->selected_page) - return FALSE; +static void book_view_layout_into (BookView* self, gint width, gint height, gint* book_width, gint* book_height) { + gint _book_width = 0; + gint _book_height = 0; + gint max_dpi; + gint max_width; + gint max_height; + gdouble aspect; + gdouble max_aspect; + gint spacing; + gint x_offset; + g_return_if_fail (self != NULL); + max_dpi = 0; + { + gint i; + i = 0; + { + gboolean _tmp0_; + _tmp0_ = TRUE; + while (TRUE) { + guint _tmp1_; + Page* _tmp2_ = NULL; + Page* page; + gint _tmp3_; + if (!_tmp0_) { + i++; + } + _tmp0_ = FALSE; + _tmp1_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp1_)) { + break; + } + _tmp2_ = book_get_page (self->priv->book, i); + page = _tmp2_; + _tmp3_ = page_get_dpi (page); + if (_tmp3_ > max_dpi) { + gint _tmp4_; + _tmp4_ = page_get_dpi (page); + max_dpi = _tmp4_; + } + _page_unref0 (page); + } + } + } + max_width = 0; + max_height = 0; + { + gint i; + i = 0; + { + gboolean _tmp5_; + _tmp5_ = TRUE; + while (TRUE) { + guint _tmp6_; + Page* _tmp7_ = NULL; + Page* page; + gint _tmp8_; + gint w; + gint _tmp9_; + gint h; + gint _tmp10_; + gint _tmp11_; + if (!_tmp5_) { + i++; + } + _tmp5_ = FALSE; + _tmp6_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp6_)) { + break; + } + _tmp7_ = book_get_page (self->priv->book, i); + page = _tmp7_; + _tmp8_ = page_get_width (page); + w = _tmp8_; + _tmp9_ = page_get_height (page); + h = _tmp9_; + _tmp10_ = page_get_dpi (page); + w = (gint) (((((gdouble) w) * max_dpi) / _tmp10_) + 0.5); + _tmp11_ = page_get_dpi (page); + h = (gint) (((((gdouble) h) * max_dpi) / _tmp11_) + 0.5); + if (w > max_width) { + max_width = w; + } + if (h > max_height) { + max_height = h; + } + _page_unref0 (page); + } + } + } + aspect = ((gdouble) width) / height; + max_aspect = ((gdouble) max_width) / max_height; + spacing = 12; + _book_width = 0; + _book_height = 0; + { + gint i; + i = 0; + { + gboolean _tmp12_; + _tmp12_ = TRUE; + while (TRUE) { + guint _tmp13_; + PageView* _tmp14_ = NULL; + PageView* page; + Page* _tmp15_ = NULL; + Page* p; + gint _tmp20_; + gint h; + gint _tmp21_; + if (!_tmp12_) { + i++; + } + _tmp12_ = FALSE; + _tmp13_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp13_)) { + break; + } + _tmp14_ = book_view_get_nth_page (self, i); + page = _tmp14_; + _tmp15_ = page_view_get_page (page); + p = _tmp15_; + if (max_aspect > aspect) { + gint _tmp16_; + gint _tmp17_; + gint w; + _tmp16_ = page_get_width (p); + _tmp17_ = page_get_dpi (p); + w = (gint) (((((gdouble) _tmp16_) * max_dpi) * width) / (_tmp17_ * max_width)); + page_view_set_width (page, w); + } else { + gint _tmp18_; + gint _tmp19_; + gint h; + _tmp18_ = page_get_height (p); + _tmp19_ = page_get_dpi (p); + h = (gint) (((((gdouble) _tmp18_) * max_dpi) * height) / (_tmp19_ * max_height)); + page_view_set_height (page, h); + } + _tmp20_ = page_view_get_height (page); + h = _tmp20_; + if (h > _book_height) { + _book_height = h; + } + _tmp21_ = page_view_get_width (page); + _book_width = _book_width + _tmp21_; + if (i != 0) { + _book_width = _book_width + spacing; + } + _page_unref0 (p); + _page_view_unref0 (page); + } + } + } + x_offset = 0; + { + gint i; + i = 0; + { + gboolean _tmp22_; + _tmp22_ = TRUE; + while (TRUE) { + guint _tmp23_; + PageView* _tmp24_ = NULL; + PageView* page; + gint _tmp25_; + gint _tmp26_; + if (!_tmp22_) { + i++; + } + _tmp22_ = FALSE; + _tmp23_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp23_)) { + break; + } + _tmp24_ = book_view_get_nth_page (self, i); + page = _tmp24_; + page_view_set_x_offset (page, x_offset); + _tmp25_ = page_view_get_width (page); + x_offset = x_offset + (_tmp25_ + spacing); + _tmp26_ = page_view_get_height (page); + page_view_set_y_offset (page, (height - _tmp26_) / 2); + _page_view_unref0 (page); + } + } + } + if (book_width) { + *book_width = _book_width; + } + if (book_height) { + *book_height = _book_height; + } +} - /* Modify page */ - if (event->button == 1) { - if (event->type == GDK_BUTTON_PRESS) - page_view_button_press (view->priv->selected_page, x, y); - else if (event->type == GDK_BUTTON_RELEASE) - page_view_button_release (view->priv->selected_page, x, y); - else if (event->type == GDK_2BUTTON_PRESS) - g_signal_emit (view, signals[SHOW_PAGE], 0, book_view_get_selected (view)); - } - - /* Show pop-up menu on right click */ - if (event->button == 3) - g_signal_emit (view, signals[SHOW_MENU], 0); - return FALSE; +static void book_view_layout (BookView* self) { + GtkAllocation allocation = {0}; + GtkAllocation _tmp0_ = {0}; + GtkAllocation box_allocation = {0}; + GtkAllocation _tmp1_ = {0}; + gboolean right_aligned; + gdouble _tmp2_; + gdouble _tmp3_; + gdouble _tmp4_; + gint width; + guint _tmp5_; + gint height; + gint book_width = 0; + gint book_height = 0; + gint _tmp6_; + gint _tmp7_; + g_return_if_fail (self != NULL); + if (!self->priv->need_layout) { + return; + } + self->priv->laying_out = TRUE; + gtk_widget_get_allocation (self->priv->drawing_area, &_tmp0_); + allocation = _tmp0_; + gtk_widget_get_allocation ((GtkWidget*) self, &_tmp1_); + box_allocation = _tmp1_; + right_aligned = TRUE; + _tmp2_ = gtk_adjustment_get_value (self->priv->adjustment); + _tmp3_ = gtk_adjustment_get_upper (self->priv->adjustment); + _tmp4_ = gtk_adjustment_get_page_size (self->priv->adjustment); + if (_tmp2_ < (_tmp3_ - _tmp4_)) { + right_aligned = FALSE; + } + width = (gint) allocation.width; + _tmp5_ = gtk_container_get_border_width ((GtkContainer*) self); + height = (gint) (box_allocation.height - (_tmp5_ * 2)); + book_view_layout_into (self, width, height, &_tmp6_, &_tmp7_); + book_width = _tmp6_; + book_height = _tmp7_; + if (book_width > allocation.width) { + gint _tmp8_; + gint _tmp9_; + gint max_offset; + gboolean _tmp10_ = FALSE; + height = allocation.height; + book_view_layout_into (self, width, height, &_tmp8_, &_tmp9_); + book_width = _tmp8_; + book_height = _tmp9_; + gtk_adjustment_set_lower (self->priv->adjustment, (gdouble) 0); + gtk_adjustment_set_upper (self->priv->adjustment, (gdouble) book_width); + gtk_adjustment_set_page_size (self->priv->adjustment, (gdouble) allocation.width); + max_offset = book_width - allocation.width; + if (right_aligned) { + _tmp10_ = TRUE; + } else { + gint _tmp11_; + _tmp11_ = book_view_get_x_offset (self); + _tmp10_ = _tmp11_ > max_offset; + } + if (_tmp10_) { + book_view_set_x_offset (self, max_offset); + } + gtk_widget_show ((GtkWidget*) self->priv->scroll); + } else { + gint offset; + gtk_widget_hide ((GtkWidget*) self->priv->scroll); + offset = (book_width - allocation.width) / 2; + gtk_adjustment_set_lower (self->priv->adjustment, (gdouble) offset); + gtk_adjustment_set_upper (self->priv->adjustment, (gdouble) offset); + gtk_adjustment_set_page_size (self->priv->adjustment, (gdouble) 0); + book_view_set_x_offset (self, offset); + } + if (self->priv->show_selected_page) { + book_view_show_page_view (self, self->priv->selected_page); + } + self->priv->need_layout = FALSE; + self->priv->show_selected_page = FALSE; + self->priv->laying_out = FALSE; } -static void -set_cursor (BookView *view, gint cursor) -{ - GdkCursor *c; - - if (view->priv->cursor == cursor) - return; - view->priv->cursor = cursor; +static gboolean book_view_draw_cb (BookView* self, GtkWidget* widget, cairo_t* context) { + gboolean result = FALSE; + guint _tmp0_; + gdouble left = 0.0; + gdouble top = 0.0; + gdouble right = 0.0; + gdouble bottom = 0.0; + gdouble _tmp1_; + gdouble _tmp2_; + gdouble _tmp3_; + gdouble _tmp4_; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (context != NULL, FALSE); + _tmp0_ = book_get_n_pages (self->priv->book); + if (_tmp0_ == ((guint) 0)) { + result = FALSE; + return result; + } + book_view_layout (self); + cairo_clip_extents (context, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_); + left = _tmp1_; + top = _tmp2_; + right = _tmp3_; + bottom = _tmp4_; + { + gint i; + i = 0; + { + gboolean _tmp5_; + _tmp5_ = TRUE; + while (TRUE) { + guint _tmp6_; + PageView* _tmp7_ = NULL; + PageView* page; + gint _tmp8_; + gint _tmp9_; + gint left_edge; + gint _tmp10_; + gint _tmp11_; + gint _tmp12_; + gint right_edge; + gboolean _tmp13_ = FALSE; + gint _tmp14_; + gboolean _tmp15_; + if (!_tmp5_) { + i++; + } + _tmp5_ = FALSE; + _tmp6_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp6_)) { + break; + } + _tmp7_ = book_view_get_nth_page (self, i); + page = _tmp7_; + _tmp8_ = page_view_get_x_offset (page); + _tmp9_ = book_view_get_x_offset (self); + left_edge = _tmp8_ - _tmp9_; + _tmp10_ = page_view_get_x_offset (page); + _tmp11_ = page_view_get_width (page); + _tmp12_ = book_view_get_x_offset (self); + right_edge = (_tmp10_ + _tmp11_) - _tmp12_; + if (((gdouble) right_edge) < left) { + _tmp13_ = TRUE; + } else { + _tmp13_ = ((gdouble) left_edge) > right; + } + if (_tmp13_) { + _page_view_unref0 (page); + continue; + } + cairo_save (context); + _tmp14_ = book_view_get_x_offset (self); + cairo_translate (context, (gdouble) (-_tmp14_), (gdouble) 0); + page_view_render (page, context); + cairo_restore (context); + _tmp15_ = page_view_get_selected (page); + if (_tmp15_) { + GtkStyle* _tmp16_ = NULL; + gint _tmp17_; + gint _tmp18_; + gint _tmp19_; + gint _tmp20_; + gint _tmp21_; + _tmp16_ = gtk_widget_get_style (self->priv->drawing_area); + _tmp17_ = page_view_get_x_offset (page); + _tmp18_ = book_view_get_x_offset (self); + _tmp19_ = page_view_get_y_offset (page); + _tmp20_ = page_view_get_width (page); + _tmp21_ = page_view_get_height (page); + gtk_paint_focus (_tmp16_, context, GTK_STATE_SELECTED, NULL, NULL, _tmp17_ - _tmp18_, _tmp19_, _tmp20_, _tmp21_); + } + _page_view_unref0 (page); + } + } + } + result = FALSE; + return result; +} + - c = gdk_cursor_new (cursor); - gdk_window_set_cursor (gtk_widget_get_window (view->priv->drawing_area), c); - gdk_cursor_destroy (c); +static PageView* book_view_get_page_at (BookView* self, gint x, gint y, gint* x_, gint* y_) { + gint _x_ = 0; + gint _y_ = 0; + PageView* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + { + gint i; + i = 0; + { + gboolean _tmp0_; + _tmp0_ = TRUE; + while (TRUE) { + guint _tmp1_; + PageView* _tmp2_ = NULL; + PageView* page; + gint _tmp3_; + gint left; + gint _tmp4_; + gint right; + gint _tmp5_; + gint top; + gint _tmp6_; + gint bottom; + gboolean _tmp7_ = FALSE; + gboolean _tmp8_ = FALSE; + gboolean _tmp9_ = FALSE; + if (!_tmp0_) { + i++; + } + _tmp0_ = FALSE; + _tmp1_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp1_)) { + break; + } + _tmp2_ = book_view_get_nth_page (self, i); + page = _tmp2_; + _tmp3_ = page_view_get_x_offset (page); + left = _tmp3_; + _tmp4_ = page_view_get_width (page); + right = left + _tmp4_; + _tmp5_ = page_view_get_y_offset (page); + top = _tmp5_; + _tmp6_ = page_view_get_height (page); + bottom = top + _tmp6_; + if (x >= left) { + _tmp9_ = x <= right; + } else { + _tmp9_ = FALSE; + } + if (_tmp9_) { + _tmp8_ = y >= top; + } else { + _tmp8_ = FALSE; + } + if (_tmp8_) { + _tmp7_ = y <= bottom; + } else { + _tmp7_ = FALSE; + } + if (_tmp7_) { + _x_ = x - left; + _y_ = y - top; + result = page; + if (x_) { + *x_ = _x_; + } + if (y_) { + *y_ = _y_; + } + return result; + } + _page_view_unref0 (page); + } + } + } + result = NULL; + if (x_) { + *x_ = _x_; + } + if (y_) { + *y_ = _y_; + } + return result; } -static gboolean -motion_cb (GtkWidget *widget, GdkEventMotion *event, BookView *view) -{ - gint x, y; - gint cursor = GDK_ARROW; - - /* Dragging */ - if (view->priv->selected_page && (event->state & GDK_BUTTON1_MASK) != 0) { - x = event->x + get_x_offset (view) - page_view_get_x_offset (view->priv->selected_page); - y = event->y - page_view_get_y_offset (view->priv->selected_page); - page_view_motion (view->priv->selected_page, x, y); - cursor = page_view_get_cursor (view->priv->selected_page); - } - else { - PageView *over_page; - over_page = get_page_at (view, event->x + get_x_offset (view), event->y, &x, &y); - if (over_page) { - page_view_motion (over_page, x, y); - cursor = page_view_get_cursor (over_page); - } - } +static gboolean book_view_button_cb (BookView* self, GtkWidget* widget, GdkEventButton* event) { + gboolean result = FALSE; + gint x; + gint y; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + book_view_layout (self); + gtk_widget_grab_focus (self->priv->drawing_area); + x = 0; + y = 0; + if ((*event).type == GDK_BUTTON_PRESS) { + gint _tmp0_; + gint _tmp1_; + gint _tmp2_; + PageView* _tmp3_ = NULL; + PageView* _tmp4_; + _tmp0_ = book_view_get_x_offset (self); + _tmp3_ = book_view_get_page_at (self, (gint) ((*event).x + _tmp0_), (gint) (*event).y, &_tmp1_, &_tmp2_); + x = _tmp1_; + y = _tmp2_; + _tmp4_ = _tmp3_; + book_view_select_page_view (self, _tmp4_); + _page_view_unref0 (_tmp4_); + } + if (self->priv->selected_page == NULL) { + result = FALSE; + return result; + } + if ((*event).button == ((guint) 1)) { + if ((*event).type == GDK_BUTTON_PRESS) { + page_view_button_press (self->priv->selected_page, x, y); + } else { + if ((*event).type == GDK_BUTTON_RELEASE) { + page_view_button_release (self->priv->selected_page, x, y); + } else { + if ((*event).type == GDK_2BUTTON_PRESS) { + Page* _tmp5_ = NULL; + Page* _tmp6_; + _tmp5_ = book_view_get_selected (self); + _tmp6_ = _tmp5_; + g_signal_emit_by_name (self, "show-page", _tmp6_); + _page_unref0 (_tmp6_); + } + } + } + } + if ((*event).button == ((guint) 3)) { + g_signal_emit_by_name (self, "show-menu"); + } + result = FALSE; + return result; +} - set_cursor (view, cursor); - return FALSE; +static void book_view_set_cursor (BookView* self, GdkCursorType cursor) { + GdkCursor* c = NULL; + GdkCursor* _tmp0_ = NULL; + GdkWindow* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + if (self->priv->cursor == cursor) { + _g_object_unref0 (c); + return; + } + self->priv->cursor = cursor; + _tmp0_ = gdk_cursor_new (cursor); + _g_object_unref0 (c); + c = _tmp0_; + _tmp1_ = gtk_widget_get_window (self->priv->drawing_area); + gdk_window_set_cursor (_tmp1_, c); + _g_object_unref0 (c); } -static gboolean -key_cb (GtkWidget *widget, GdkEventKey *event, BookView *view) -{ - switch (event->keyval) { - case GDK_Home: - book_view_select_page (view, book_get_page (view->priv->book, 0)); - return TRUE; - case GDK_Left: - select_page (view, get_prev_page (view, view->priv->selected_page)); - return TRUE; - case GDK_Right: - select_page (view, get_next_page (view, view->priv->selected_page)); - return TRUE; - case GDK_End: - book_view_select_page (view, book_get_page (view->priv->book, book_get_n_pages (view->priv->book) - 1)); - return TRUE; +static gboolean book_view_motion_cb (BookView* self, GtkWidget* widget, GdkEventMotion* event) { + gboolean result = FALSE; + GdkCursorType cursor; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + cursor = GDK_ARROW; + if (self->priv->selected_page != NULL) { + _tmp0_ = ((*event).state & GDK_BUTTON1_MASK) != 0; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + gint _tmp1_; + gint _tmp2_; + gint x; + gint _tmp3_; + gint y; + GdkCursorType _tmp4_; + _tmp1_ = book_view_get_x_offset (self); + _tmp2_ = page_view_get_x_offset (self->priv->selected_page); + x = (gint) (((*event).x + _tmp1_) - _tmp2_); + _tmp3_ = page_view_get_y_offset (self->priv->selected_page); + y = (gint) ((*event).y - _tmp3_); + page_view_motion (self->priv->selected_page, x, y); + _tmp4_ = page_view_get_cursor (self->priv->selected_page); + cursor = _tmp4_; + } else { + gint x = 0; + gint y = 0; + gint _tmp5_; + gint _tmp6_; + gint _tmp7_; + PageView* _tmp8_ = NULL; + PageView* over_page; + _tmp5_ = book_view_get_x_offset (self); + _tmp8_ = book_view_get_page_at (self, (gint) ((*event).x + _tmp5_), (gint) (*event).y, &_tmp6_, &_tmp7_); + x = _tmp6_; + y = _tmp7_; + over_page = _tmp8_; + if (over_page != NULL) { + GdkCursorType _tmp9_; + page_view_motion (over_page, x, y); + _tmp9_ = page_view_get_cursor (over_page); + cursor = _tmp9_; + } + _page_view_unref0 (over_page); + } + book_view_set_cursor (self, cursor); + result = FALSE; + return result; +} + - default: - return FALSE; - } +static gboolean book_view_key_cb (BookView* self, GtkWidget* widget, GdkEventKey* event) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + switch ((*event).keyval) { + case 0xff50: + { + Page* _tmp0_ = NULL; + Page* _tmp1_; + _tmp0_ = book_get_page (self->priv->book, 0); + _tmp1_ = _tmp0_; + book_view_select_page (self, _tmp1_); + _page_unref0 (_tmp1_); + result = TRUE; + return result; + } + case 0xff51: + { + PageView* _tmp2_ = NULL; + PageView* _tmp3_; + _tmp2_ = book_view_get_prev_page (self, self->priv->selected_page); + _tmp3_ = _tmp2_; + book_view_select_page_view (self, _tmp3_); + _page_view_unref0 (_tmp3_); + result = TRUE; + return result; + } + case 0xff53: + { + PageView* _tmp4_ = NULL; + PageView* _tmp5_; + _tmp4_ = book_view_get_next_page (self, self->priv->selected_page); + _tmp5_ = _tmp4_; + book_view_select_page_view (self, _tmp5_); + _page_view_unref0 (_tmp5_); + result = TRUE; + return result; + } + case 0xFF57: + { + guint _tmp6_; + Page* _tmp7_ = NULL; + Page* _tmp8_; + _tmp6_ = book_get_n_pages (self->priv->book); + _tmp7_ = book_get_page (self->priv->book, ((gint) _tmp6_) - 1); + _tmp8_ = _tmp7_; + book_view_select_page (self, _tmp8_); + _page_unref0 (_tmp8_); + result = TRUE; + return result; + } + default: + { + result = FALSE; + return result; + } + } } -static gboolean -focus_cb (GtkWidget *widget, GdkEventFocus *event, BookView *view) -{ - set_selected_page (view, view->priv->selected_page); - return FALSE; +static gboolean book_view_focus_cb (BookView* self, GtkWidget* widget, GdkEventFocus* event) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + book_view_set_selected_page (self, self->priv->selected_page); + result = FALSE; + return result; } -static void -scroll_cb (GtkAdjustment *adjustment, BookView *view) -{ - if (!view->priv->laying_out) - book_view_redraw (view); +static void book_view_scroll_cb (BookView* self, GtkAdjustment* adjustment) { + g_return_if_fail (self != NULL); + g_return_if_fail (adjustment != NULL); + if (!self->priv->laying_out) { + book_view_redraw (self); + } } -void -book_view_redraw (BookView *view) -{ - g_return_if_fail (view != NULL); - gtk_widget_queue_draw (view->priv->drawing_area); +void book_view_redraw (BookView* self) { + g_return_if_fail (self != NULL); + gtk_widget_queue_draw (self->priv->drawing_area); } -void -book_view_select_page (BookView *view, Page *page) -{ - g_return_if_fail (view != NULL); +void book_view_select_page (BookView* self, Page* page) { + Page* _tmp0_ = NULL; + Page* _tmp1_; + gboolean _tmp2_; + g_return_if_fail (self != NULL); + _tmp0_ = book_view_get_selected (self); + _tmp1_ = _tmp0_; + _tmp2_ = _tmp1_ == page; + _page_unref0 (_tmp1_); + if (_tmp2_) { + return; + } + if (page != NULL) { + gconstpointer _tmp3_ = NULL; + _tmp3_ = g_hash_table_lookup (self->priv->page_data, page); + book_view_select_page_view (self, (PageView*) _tmp3_); + } else { + book_view_select_page_view (self, NULL); + } +} - if (book_view_get_selected (view) == page) - return; - if (page) - select_page (view, g_hash_table_lookup (view->priv->page_data, page)); - else - select_page (view, NULL); +void book_view_select_next_page (BookView* self) { + PageView* _tmp0_ = NULL; + PageView* _tmp1_; + g_return_if_fail (self != NULL); + _tmp0_ = book_view_get_next_page (self, self->priv->selected_page); + _tmp1_ = _tmp0_; + book_view_select_page_view (self, _tmp1_); + _page_view_unref0 (_tmp1_); } -void -book_view_select_next_page (BookView *view) -{ - g_return_if_fail (view != NULL); - select_page (view, get_next_page (view, view->priv->selected_page)); +void book_view_select_prev_page (BookView* self) { + PageView* _tmp0_ = NULL; + PageView* _tmp1_; + g_return_if_fail (self != NULL); + _tmp0_ = book_view_get_prev_page (self, self->priv->selected_page); + _tmp1_ = _tmp0_; + book_view_select_page_view (self, _tmp1_); + _page_view_unref0 (_tmp1_); } -void -book_view_select_prev_page (BookView *view) -{ - g_return_if_fail (view != NULL); - select_page (view, get_prev_page (view, view->priv->selected_page)); +Page* book_view_get_selected (BookView* self) { + Page* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + if (self->priv->selected_page != NULL) { + Page* _tmp0_ = NULL; + _tmp0_ = page_view_get_page (self->priv->selected_page); + result = _tmp0_; + return result; + } else { + result = NULL; + return result; + } } -Page * -book_view_get_selected (BookView *view) -{ - g_return_val_if_fail (view != NULL, NULL); +static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__PAGE) (gpointer data1, gpointer arg_1, gpointer data2); + register GMarshalFunc_VOID__PAGE callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 2); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__PAGE) (marshal_data ? marshal_data : cc->callback); + callback (data1, value_get_page (param_values + 1), data2); +} - if (view->priv->selected_page) - return page_view_get_page (view->priv->selected_page); - else - return NULL; + +static void book_view_class_init (BookViewClass * klass) { + book_view_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (klass, sizeof (BookViewPrivate)); + G_OBJECT_CLASS (klass)->finalize = book_view_finalize; + g_signal_new ("page_selected", TYPE_BOOK_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE); + g_signal_new ("show_page", TYPE_BOOK_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE); + g_signal_new ("show_menu", TYPE_BOOK_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } -static void -book_view_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BookView *self; - gint i, n_pages; - - self = BOOK_VIEW (object); - - switch (prop_id) { - case PROP_BOOK: - self->priv->book = g_object_ref (g_value_get_object (value)); +static void book_view_instance_init (BookView * self) { + self->priv = BOOK_VIEW_GET_PRIVATE (self); + self->priv->selected_page = NULL; +} + - /* Load existing pages */ - n_pages = book_get_n_pages (self->priv->book); - for (i = 0; i < n_pages; i++) { - Page *page = book_get_page (self->priv->book, i); - add_cb (self->priv->book, page, self); - } +static void book_view_finalize (GObject* obj) { + BookView * self; + self = BOOK_VIEW (obj); + _book_unref0 (self->priv->book); + _g_hash_table_unref0 (self->priv->page_data); + _page_view_unref0 (self->priv->selected_page); + _g_object_unref0 (self->priv->drawing_area); + _g_object_unref0 (self->priv->scroll); + _g_object_unref0 (self->priv->adjustment); + G_OBJECT_CLASS (book_view_parent_class)->finalize (obj); +} - book_view_select_page (self, book_get_page (self->priv->book, 0)); - /* Watch for new pages */ - g_signal_connect (self->priv->book, "page-added", G_CALLBACK (add_cb), self); - g_signal_connect (self->priv->book, "page-removed", G_CALLBACK (remove_cb), self); - g_signal_connect (self->priv->book, "reordered", G_CALLBACK (reorder_cb), self); - g_signal_connect (self->priv->book, "cleared", G_CALLBACK (clear_cb), self); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -book_view_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BookView *self; - - self = BOOK_VIEW (object); - - switch (prop_id) { - case PROP_BOOK: - g_value_set_object (value, self->priv->book); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -book_view_finalize (GObject *object) -{ - BookView *view = BOOK_VIEW (object); - g_object_unref (view->priv->book); - view->priv->book = NULL; - g_hash_table_unref (view->priv->page_data); - view->priv->page_data = NULL; - G_OBJECT_CLASS (book_view_parent_class)->finalize (object); -} - - -static void -book_view_class_init (BookViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = book_view_finalize; - object_class->set_property = book_view_set_property; - object_class->get_property = book_view_get_property; - - signals[PAGE_SELECTED] = - g_signal_new ("page-selected", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookViewClass, page_selected), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, page_get_type ()); - signals[SHOW_PAGE] = - g_signal_new ("show-page", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookViewClass, show_page), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, page_get_type ()); - signals[SHOW_MENU] = - g_signal_new ("show-menu", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookViewClass, show_page), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_object_class_install_property(object_class, - PROP_BOOK, - g_param_spec_object("book", - "book", - "Book being shown", - book_get_type(), - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (BookViewPrivate)); -} - - -static void -book_view_init (BookView *view) -{ - view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, BOOK_VIEW_TYPE, BookViewPrivate); - view->priv->need_layout = TRUE; - view->priv->page_data = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) g_object_unref); - view->priv->cursor = GDK_ARROW; - - view->priv->drawing_area = gtk_drawing_area_new (); - gtk_widget_set_size_request (view->priv->drawing_area, 200, 100); - gtk_widget_set_can_focus (view->priv->drawing_area, TRUE); - gtk_widget_set_events (view->priv->drawing_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK); - gtk_box_pack_start (GTK_BOX (view), view->priv->drawing_area, TRUE, TRUE, 0); - - view->priv->scroll = gtk_hscrollbar_new (NULL); - view->priv->adjustment = gtk_range_get_adjustment (GTK_RANGE (view->priv->scroll)); - gtk_box_pack_start (GTK_BOX (view), view->priv->scroll, FALSE, TRUE, 0); - - g_signal_connect (view->priv->drawing_area, "configure-event", G_CALLBACK (configure_cb), view); - g_signal_connect (view->priv->drawing_area, "expose-event", G_CALLBACK (expose_cb), view); - g_signal_connect (view->priv->drawing_area, "motion-notify-event", G_CALLBACK (motion_cb), view); - g_signal_connect (view->priv->drawing_area, "key-press-event", G_CALLBACK (key_cb), view); - g_signal_connect (view->priv->drawing_area, "button-press-event", G_CALLBACK (button_cb), view); - g_signal_connect (view->priv->drawing_area, "button-release-event", G_CALLBACK (button_cb), view); - g_signal_connect_after (view->priv->drawing_area, "focus-in-event", G_CALLBACK (focus_cb), view); - g_signal_connect_after (view->priv->drawing_area, "focus-out-event", G_CALLBACK (focus_cb), view); - g_signal_connect (view->priv->adjustment, "value-changed", G_CALLBACK (scroll_cb), view); - - gtk_widget_show (view->priv->drawing_area); +GType book_view_get_type (void) { + static volatile gsize book_view_type_id__volatile = 0; + if (g_once_init_enter (&book_view_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (BookViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) book_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (BookView), 0, (GInstanceInitFunc) book_view_instance_init, NULL }; + GType book_view_type_id; + book_view_type_id = g_type_register_static (GTK_TYPE_VBOX, "BookView", &g_define_type_info, 0); + g_once_init_leave (&book_view_type_id__volatile, book_view_type_id); + } + return book_view_type_id__volatile; } + + + diff --git a/src/book-view.h b/src/book-view.h deleted file mode 100644 index 5b5e2a6..0000000 --- a/src/book-view.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2009 Canonical Ltd. - * Author: Robert Ancell <robert.ancell@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. See http://www.gnu.org/copyleft/gpl.html the full text of the - * license. - */ - -#ifndef _BOOK_VIEW_H_ -#define _BOOK_VIEW_H_ - -#include <gtk/gtk.h> -#include <cairo.h> -#include "book.h" - -G_BEGIN_DECLS - -#define BOOK_VIEW_TYPE (book_view_get_type ()) -#define BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BOOK_VIEW_TYPE, BookView)) - - -typedef struct BookViewPrivate BookViewPrivate; - -typedef struct -{ - GtkVBox parent_instance; - BookViewPrivate *priv; -} BookView; - -typedef struct -{ - GtkVBoxClass parent_class; - - void (*page_selected) (BookView *view, Page *page); - void (*show_page) (BookView *view, Page *page); - void (*show_menu) (BookView *view, Page *page); -} BookViewClass; - - -GType book_view_get_type (void); - -BookView *book_view_new (Book *book); - -void book_view_redraw (BookView *view); - -Book *book_view_get_book (BookView *view); - -void book_view_select_page (BookView *view, Page *page); - -void book_view_select_next_page (BookView *view); - -void book_view_select_prev_page (BookView *view); - -Page *book_view_get_selected (BookView *view); - -#endif /* _BOOK_VIEW_H_ */ diff --git a/src/book-view.vala b/src/book-view.vala new file mode 100644 index 0000000..9dfd361 --- /dev/null +++ b/src/book-view.vala @@ -0,0 +1,594 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +// FIXME: When scrolling, copy existing render sideways? +// FIXME: Only render pages that change and only the part that changed + +public class BookView : Gtk.VBox +{ + /* Book being rendered */ + private Book book; + private HashTable<Page, PageView> page_data; + + /* True if the view needs to be laid out again */ + private bool need_layout; + private bool laying_out; + private bool show_selected_page; + + /* Currently selected page */ + private PageView? selected_page = null; + + /* Widget being rendered to */ + private Gtk.Widget drawing_area; + + /* Horizontal scrollbar */ + private Gtk.HScrollbar scroll; + private Gtk.Adjustment adjustment; + + private Gdk.CursorType cursor; + + public signal void page_selected (Page? page); + public signal void show_page (Page page); + public signal void show_menu (); + + public BookView (Book book) + { + this.book = book; + + /* Load existing pages */ + for (var i = 0; i < book.get_n_pages (); i++) + { + Page page = book.get_page (i); + add_cb (book, page); + } + + select_page (book.get_page (0)); + + /* Watch for new pages */ + book.page_added.connect (add_cb); + book.page_removed.connect (remove_cb); + book.reordered.connect (reorder_cb); + book.cleared.connect (clear_cb); + + need_layout = true; + page_data = new HashTable<Page, PageView> (direct_hash, direct_equal); + cursor = Gdk.CursorType.ARROW; + + drawing_area = new Gtk.DrawingArea (); + drawing_area.set_size_request (200, 100); + drawing_area.set_can_focus (true); + drawing_area.set_events (Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.FOCUS_CHANGE_MASK | Gdk.EventMask.STRUCTURE_MASK | Gdk.EventMask.SCROLL_MASK); + pack_start (drawing_area, true, true, 0); + + scroll = new Gtk.HScrollbar (null); + adjustment = scroll.get_adjustment (); + pack_start (scroll, false, true, 0); + + drawing_area.configure_event.connect (configure_cb); + drawing_area.draw.connect (draw_cb); + drawing_area.motion_notify_event.connect (motion_cb); + drawing_area.key_press_event.connect (key_cb); + drawing_area.button_press_event.connect (button_cb); + drawing_area.button_release_event.connect (button_cb); + drawing_area.focus_in_event.connect_after (focus_cb); + drawing_area.focus_out_event.connect_after (focus_cb); + adjustment.value_changed.connect (scroll_cb); + + drawing_area.show (); + } + + private PageView get_nth_page (int n) + { + Page page = book.get_page (n); + return page_data.lookup (page); + } + + private PageView get_next_page (PageView page) + { + for (var i = 0; ; i++) + { + var p = book.get_page (i); + if (p == null) + break; + if (p == page.get_page ()) + { + p = book.get_page (i + 1); + if (p != null) + return page_data.lookup (p); + } + } + + return page; + } + + private PageView get_prev_page (PageView page) + { + var prev_page = page; + for (var i = 0; ; i++) + { + var p = book.get_page (i); + if (p == null) + break; + if (p == page.get_page ()) + return prev_page; + prev_page = page_data.lookup (p); + } + + return page; + } + + private void page_view_changed_cb (PageView page) + { + redraw (); + } + + private void page_view_size_changed_cb (PageView page) + { + need_layout = true; + redraw (); + } + + private void add_cb (Book book, Page page) + { + var page_view = new PageView (page); + page_view.changed.connect (page_view_changed_cb); + page_view.size_changed.connect (page_view_size_changed_cb); + page_data.insert (page, page_view); + need_layout = true; + redraw (); + } + + private void set_selected_page (PageView? page) + { + /* Deselect existing page if changed */ + if (selected_page != null && page != selected_page) + selected_page.set_selected (false); + + selected_page = page; + if (selected_page == null) + return; + + /* Select new page if widget has focus */ + if (!drawing_area.has_focus) + selected_page.set_selected (false); + else + selected_page.set_selected (true); + } + + private void set_x_offset (int offset) + { + adjustment.set_value (offset); + } + + private int get_x_offset () + { + return (int) adjustment.get_value (); + } + + private void show_page_view (PageView? page) + { + if (page == null || !scroll.get_visible ()) + return; + + Gtk.Allocation allocation; + drawing_area.get_allocation (out allocation); + var left_edge = page.get_x_offset (); + var right_edge = page.get_x_offset () + page.get_width (); + + if (left_edge - get_x_offset () < 0) + set_x_offset (left_edge); + else if (right_edge - get_x_offset () > allocation.width) + set_x_offset (right_edge - allocation.width); + } + + private void select_page_view (PageView? page) + { + Page? p = null; + + if (selected_page == page) + return; + + set_selected_page (page); + + if (need_layout) + show_selected_page = true; + else + show_page_view (page); + + if (page != null) + p = page.get_page (); + page_selected (p); + } + + private void remove_cb (Book book, Page page) + { + PageView new_selection = selected_page; + + /* Select previous page or next if removing the selected page */ + if (page == get_selected ()) + { + new_selection = get_prev_page (selected_page); + if (new_selection == selected_page) + new_selection = get_next_page (selected_page); + selected_page = null; + } + + page_data.remove (page); + + select_page_view (new_selection); + + need_layout = true; + redraw (); + } + + private void reorder_cb (Book book) + { + need_layout = true; + redraw (); + } + + private void clear_cb (Book book) + { + page_data.remove_all (); + selected_page = null; + page_selected (null); + need_layout = true; + redraw (); + } + + public Book get_book () + { + return book; + } + + private bool configure_cb (Gtk.Widget widget, Gdk.EventConfigure event) + { + need_layout = true; + return false; + } + + private void layout_into (int width, int height, out int book_width, out int book_height) + { + /* Get maximum page resolution */ + int max_dpi = 0; + for (var i = 0; i < book.get_n_pages (); i++) + { + var page = book.get_page (i); + if (page.get_dpi () > max_dpi) + max_dpi = page.get_dpi (); + } + + /* Get area required to fit all pages */ + int max_width = 0, max_height = 0; + for (var i = 0; i < book.get_n_pages (); i++) + { + var page = book.get_page (i); + var w = page.get_width (); + var h = page.get_height (); + + /* Scale to the same DPI */ + w = (int) ((double)w * max_dpi / page.get_dpi () + 0.5); + h = (int) ((double)h * max_dpi / page.get_dpi () + 0.5); + + if (w > max_width) + max_width = w; + if (h > max_height) + max_height = h; + } + + var aspect = (double)width / height; + var max_aspect = (double)max_width / max_height; + + /* Get total dimensions of all pages */ + int spacing = 12; + book_width = 0; + book_height = 0; + for (var i = 0; i < book.get_n_pages (); i++) + { + var page = get_nth_page (i); + var p = page.get_page (); + + /* NOTE: Using double to avoid overflow for large images */ + if (max_aspect > aspect) + { + /* Set width scaled on DPI and maximum width */ + int w = (int) ((double)p.get_width () * max_dpi * width / (p.get_dpi () * max_width)); + page.set_width (w); + } + else + { + /* Set height scaled on DPI and maximum height */ + int h = (int) ((double)p.get_height () * max_dpi * height / (p.get_dpi () * max_height)); + page.set_height (h); + } + + var h = page.get_height (); + if (h > book_height) + book_height = h; + book_width += page.get_width (); + if (i != 0) + book_width += spacing; + } + + int x_offset = 0; + for (var i = 0; i < book.get_n_pages (); i++) + { + var page = get_nth_page (i); + + /* Layout pages left to right */ + page.set_x_offset (x_offset); + x_offset += page.get_width () + spacing; + + /* Centre page vertically */ + page.set_y_offset ((height - page.get_height ()) / 2); + } + } + + private void layout () + { + if (!need_layout) + return; + + laying_out = true; + + Gtk.Allocation allocation; + drawing_area.get_allocation(out allocation); + Gtk.Allocation box_allocation; + get_allocation(out box_allocation); + + /* If scroll is right aligned then keep that after layout */ + bool right_aligned = true; + if (adjustment.get_value () < adjustment.get_upper () - adjustment.get_page_size ()) + right_aligned = false; + + /* Try and fit without scrollbar */ + var width = (int) allocation.width; + var height = (int) (box_allocation.height - get_border_width () * 2); + int book_width, book_height; + layout_into (width, height, out book_width, out book_height); + + /* Relayout with scrollbar */ + if (book_width > allocation.width) + { + /* Re-layout leaving space for scrollbar */ + height = allocation.height; + layout_into (width, height, out book_width, out book_height); + + /* Set scrollbar limits */ + adjustment.set_lower (0); + adjustment.set_upper (book_width); + adjustment.set_page_size (allocation.width); + + /* Keep right-aligned */ + var max_offset = book_width - allocation.width; + if (right_aligned || get_x_offset () > max_offset) + set_x_offset(max_offset); + + scroll.show (); + } + else + { + scroll.hide (); + var offset = (book_width - allocation.width) / 2; + adjustment.set_lower (offset); + adjustment.set_upper (offset); + adjustment.set_page_size (0); + set_x_offset (offset); + } + + if (show_selected_page) + show_page_view (selected_page); + + need_layout = false; + show_selected_page = false; + laying_out = false; + } + + private bool draw_cb (Gtk.Widget widget, Cairo.Context context) + { + if (book.get_n_pages () == 0) + return false; + + layout (); + + double left, top, right, bottom; + context.clip_extents (out left, out top, out right, out bottom); + + /* Render each page */ + for (var i = 0; i < book.get_n_pages (); i++) + { + var page = get_nth_page (i); + var left_edge = page.get_x_offset () - get_x_offset (); + var right_edge = page.get_x_offset () + page.get_width () - get_x_offset (); + + /* Page not visible, don't render */ + if (right_edge < left || left_edge > right) + continue; + + context.save (); + context.translate (-get_x_offset (), 0); + page.render (context); + context.restore (); + + if (page.get_selected ()) + Gtk.paint_focus (drawing_area.get_style (), + context, + Gtk.StateType.SELECTED, + null, + null, + page.get_x_offset () - get_x_offset (), + page.get_y_offset (), + page.get_width (), + page.get_height ()); + } + + return false; + } + + private PageView? get_page_at (int x, int y, out int x_, out int y_) + { + for (var i = 0; i < book.get_n_pages (); i++) + { + var page = get_nth_page (i); + var left = page.get_x_offset (); + var right = left + page.get_width (); + var top = page.get_y_offset (); + var bottom = top + page.get_height (); + if (x >= left && x <= right && y >= top && y <= bottom) + { + x_ = x - left; + y_ = y - top; + return page; + } + } + + return null; + } + + private bool button_cb (Gtk.Widget widget, Gdk.EventButton event) + { + layout (); + + drawing_area.grab_focus (); + + int x = 0, y = 0; + if (event.type == Gdk.EventType.BUTTON_PRESS) + select_page_view (get_page_at ((int) (event.x + get_x_offset ()), (int) event.y, out x, out y)); + + if (selected_page == null) + return false; + + /* Modify page */ + if (event.button == 1) + { + if (event.type == Gdk.EventType.BUTTON_PRESS) + selected_page.button_press (x, y); + else if (event.type == Gdk.EventType.BUTTON_RELEASE) + selected_page.button_release (x, y); + else if (event.type == Gdk.EventType.2BUTTON_PRESS) + show_page (get_selected ()); + } + + /* Show pop-up menu on right click */ + if (event.button == 3) + show_menu (); + + return false; + } + + private void set_cursor (Gdk.CursorType cursor) + { + Gdk.Cursor c; + + if (this.cursor == cursor) + return; + this.cursor = cursor; + + c = new Gdk.Cursor (cursor); + drawing_area.get_window ().set_cursor (c); + } + + private bool motion_cb (Gtk.Widget widget, Gdk.EventMotion event) + { + Gdk.CursorType cursor = Gdk.CursorType.ARROW; + + /* Dragging */ + if (selected_page != null && (event.state & Gdk.ModifierType.BUTTON1_MASK) != 0) + { + var x = (int) (event.x + get_x_offset () - selected_page.get_x_offset ()); + var y = (int) (event.y - selected_page.get_y_offset ()); + selected_page.motion (x, y); + cursor = selected_page.get_cursor (); + } + else + { + int x, y; + var over_page = get_page_at ((int) (event.x + get_x_offset ()), (int) event.y, out x, out y); + if (over_page != null) + { + over_page.motion (x, y); + cursor = over_page.get_cursor (); + } + } + + set_cursor (cursor); + + return false; + } + + private bool key_cb (Gtk.Widget widget, Gdk.EventKey event) + { + switch (event.keyval) + { + case 0xff50: /* FIXME: GDK_Home */ + select_page (book.get_page (0)); + return true; + case 0xff51: /* FIXME: GDK_Left */ + select_page_view (get_prev_page (selected_page)); + return true; + case 0xff53: /* FIXME: GDK_Right */ + select_page_view (get_next_page (selected_page)); + return true; + case 0xFF57: /* FIXME: GDK_End */ + select_page (book.get_page ((int) book.get_n_pages () - 1)); + return true; + + default: + return false; + } + } + + private bool focus_cb (Gtk.Widget widget, Gdk.EventFocus event) + { + set_selected_page (selected_page); + return false; + } + + private void scroll_cb (Gtk.Adjustment adjustment) + { + if (!laying_out) + redraw (); + } + + public void redraw () + { + drawing_area.queue_draw (); + } + + public void select_page (Page? page) + { + if (get_selected () == page) + return; + + if (page != null) + select_page_view (page_data.lookup (page)); + else + select_page_view (null); + } + + public void select_next_page () + { + select_page_view (get_next_page (selected_page)); + } + + public void select_prev_page () + { + select_page_view (get_prev_page (selected_page)); + } + + public Page? get_selected () + { + if (selected_page != null) + return selected_page.get_page (); + else + return null; + } +} @@ -1,7 +1,10 @@ +/* book.c generated by valac 0.13.1, the Vala compiler + * generated from book.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later @@ -9,870 +12,2278 @@ * license. */ -#include <stdio.h> +#include <glib.h> +#include <glib-object.h> +#include <stdlib.h> #include <string.h> +#include <gio/gio.h> +#include <cairo.h> +#include <gdk-pixbuf/gdk-pixdata.h> +#include <float.h> #include <math.h> +#include <gdk/gdk.h> +#include <cairo-ps.h> #include <zlib.h> #include <jpeglib.h> -#include <gdk/gdk.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <cairo/cairo-pdf.h> -#include <cairo/cairo-ps.h> +#include <config.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_BOOK (book_get_type ()) +#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book)) +#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass)) +#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK)) +#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK)) +#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass)) + +typedef struct _Book Book; +typedef struct _BookClass BookClass; +typedef struct _BookPrivate BookPrivate; + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; +#define __g_list_free__page_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__page_unref0_ (var), NULL))) + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) +#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL))) + +#define TYPE_PS_WRITER (ps_writer_get_type ()) +#define PS_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PS_WRITER, PsWriter)) +#define PS_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PS_WRITER, PsWriterClass)) +#define IS_PS_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PS_WRITER)) +#define IS_PS_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PS_WRITER)) +#define PS_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PS_WRITER, PsWriterClass)) + +typedef struct _PsWriter PsWriter; +typedef struct _PsWriterClass PsWriterClass; +typedef struct _PsWriterPrivate PsWriterPrivate; +#define _cairo_surface_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_surface_destroy (var), NULL))) +#define _ps_writer_unref0(var) ((var == NULL) ? NULL : (var = (ps_writer_unref (var), NULL))) + +#define TYPE_PDF_WRITER (pdf_writer_get_type ()) +#define PDF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PDF_WRITER, PDFWriter)) +#define PDF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PDF_WRITER, PDFWriterClass)) +#define IS_PDF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PDF_WRITER)) +#define IS_PDF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PDF_WRITER)) +#define PDF_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PDF_WRITER, PDFWriterClass)) + +typedef struct _PDFWriter PDFWriter; +typedef struct _PDFWriterClass PDFWriterClass; +typedef struct _PDFWriterPrivate PDFWriterPrivate; +#define _pdf_writer_unref0(var) ((var == NULL) ? NULL : (var = (pdf_writer_unref (var), NULL))) +typedef struct _ParamSpecBook ParamSpecBook; +#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +typedef struct _ParamSpecPDFWriter ParamSpecPDFWriter; +typedef struct _ParamSpecPsWriter ParamSpecPsWriter; + +struct _Book { + GTypeInstance parent_instance; + volatile int ref_count; + BookPrivate * priv; +}; + +struct _BookClass { + GTypeClass parent_class; + void (*finalize) (Book *self); +}; + +struct _BookPrivate { + GList* pages; + gboolean needs_saving; +}; + +typedef enum { + SCAN_DIRECTION_TOP_TO_BOTTOM, + SCAN_DIRECTION_LEFT_TO_RIGHT, + SCAN_DIRECTION_BOTTOM_TO_TOP, + SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _PsWriter { + GTypeInstance parent_instance; + volatile int ref_count; + PsWriterPrivate * priv; + cairo_surface_t* surface; + GFileOutputStream* stream; +}; -#include "book.h" +struct _PsWriterClass { + GTypeClass parent_class; + void (*finalize) (PsWriter *self); +}; -enum { - PROP_0, - PROP_NEEDS_SAVING +struct _PDFWriter { + GTypeInstance parent_instance; + volatile int ref_count; + PDFWriterPrivate * priv; + gsize offset; + GList* object_offsets; }; -enum { - PAGE_ADDED, - PAGE_REMOVED, - REORDERED, - CLEARED, - LAST_SIGNAL +struct _PDFWriterClass { + GTypeClass parent_class; + void (*finalize) (PDFWriter *self); }; -static guint signals[LAST_SIGNAL] = { 0, }; -struct BookPrivate -{ - GList *pages; - - gboolean needs_saving; +struct _ParamSpecBook { + GParamSpec parent_instance; }; -G_DEFINE_TYPE (Book, book, G_TYPE_OBJECT); +struct _PDFWriterPrivate { + GFileOutputStream* stream; +}; + +struct _ParamSpecPDFWriter { + GParamSpec parent_instance; +}; + +struct _ParamSpecPsWriter { + GParamSpec parent_instance; +}; + + +static gpointer book_parent_class = NULL; +static gpointer pdf_writer_parent_class = NULL; +static gpointer ps_writer_parent_class = NULL; + +gpointer book_ref (gpointer instance); +void book_unref (gpointer instance); +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_book (GValue* value, gpointer v_object); +void value_take_book (GValue* value, gpointer v_object); +gpointer value_get_book (const GValue* value); +GType book_get_type (void) G_GNUC_CONST; +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +#define BOOK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_BOOK, BookPrivate)) +enum { + BOOK_DUMMY_PROPERTY +}; +static void _page_unref0_ (gpointer var); +static void _g_list_free__page_unref0_ (GList* self); +Book* book_new (void); +Book* book_construct (GType object_type); +void book_clear (Book* self); +static void book_page_changed_cb (Book* self, Page* page); +void book_set_needs_saving (Book* self, gboolean needs_saving); +GType scan_direction_get_type (void) G_GNUC_CONST; +Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction); +Page* page_new (gint width, gint height, gint dpi, ScanDirection scan_direction); +Page* page_construct (GType object_type, gint width, gint height, gint dpi, ScanDirection scan_direction); +static void _book_page_changed_cb_page_pixels_changed (Page* _sender, gpointer self); +static void _book_page_changed_cb_page_crop_changed (Page* _sender, gpointer self); +void book_move_page (Book* self, Page* page, guint location); +void book_delete_page (Book* self, Page* page); +guint book_get_n_pages (Book* self); +Page* book_get_page (Book* self, gint page_number); +guint book_get_page_index (Book* self, Page* page); +static GFile* book_make_indexed_file (Book* self, const gchar* uri, gint i); +static void book_save_multi_file (Book* self, const gchar* type, GFile* file, GError** error); +void page_save (Page* self, const gchar* type, GFile* file, GError** error); +static void book_save_ps_pdf_surface (Book* self, cairo_surface_t* surface, GdkPixbuf* image, gdouble dpi); +static void book_save_ps (Book* self, GFile* file, GError** error); +PsWriter* ps_writer_new (GFileOutputStream* stream); +PsWriter* ps_writer_construct (GType object_type, GFileOutputStream* stream); +gpointer ps_writer_ref (gpointer instance); +void ps_writer_unref (gpointer instance); +GParamSpec* param_spec_ps_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_ps_writer (GValue* value, gpointer v_object); +void value_take_ps_writer (GValue* value, gpointer v_object); +gpointer value_get_ps_writer (const GValue* value); +GType ps_writer_get_type (void) G_GNUC_CONST; +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop); +gint page_get_dpi (Page* self); +static guint8* book_compress_zlib (Book* self, guint8* data, int data_length1, int* result_length1); +static void book_jpeg_init_cb (struct jpeg_compress_struct* info); +static gboolean book_jpeg_empty_cb (struct jpeg_compress_struct* info); +static void book_jpeg_term_cb (struct jpeg_compress_struct* info); +static guint8* book_compress_jpeg (Book* self, GdkPixbuf* image, gsize* n_written, int* result_length1); +static void _book_jpeg_init_cb_jpeg_initdestinationfunc (struct jpeg_compress_struct* cinfo); +static gboolean _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc (struct jpeg_compress_struct* cinfo); +static void _book_jpeg_term_cb_jpeg_termdestinationfunc (struct jpeg_compress_struct* cinfo); +static void book_save_pdf (Book* self, GFile* file, GError** error); +PDFWriter* pdf_writer_new (GFileOutputStream* stream); +PDFWriter* pdf_writer_construct (GType object_type, GFileOutputStream* stream); +gpointer pdf_writer_ref (gpointer instance); +void pdf_writer_unref (gpointer instance); +GParamSpec* param_spec_pdf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_pdf_writer (GValue* value, gpointer v_object); +void value_take_pdf_writer (GValue* value, gpointer v_object); +gpointer value_get_pdf_writer (const GValue* value); +GType pdf_writer_get_type (void) G_GNUC_CONST; +void pdf_writer_write_string (PDFWriter* self, const gchar* text); +guint pdf_writer_start_object (PDFWriter* self); +gboolean page_is_color (Page* self); +gint page_get_depth (Page* self); +static guint8* _vala_array_dup1 (guint8* self, int length); +static guint8* _vala_array_dup2 (guint8* self, int length); +void pdf_writer_write (PDFWriter* self, guint8* data, int data_length1); +void book_save (Book* self, const gchar* type, GFile* file, GError** error); +gboolean book_get_needs_saving (Book* self); +static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void book_finalize (Book* obj); +#define PDF_WRITER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PDF_WRITER, PDFWriterPrivate)) +enum { + PDF_WRITER_DUMMY_PROPERTY +}; +static void pdf_writer_finalize (PDFWriter* obj); +enum { + PS_WRITER_DUMMY_PROPERTY +}; +static cairo_status_t ps_writer_write_cairo_data (PsWriter* self, guint8* data, int data_length1); +static cairo_status_t _ps_writer_write_cairo_data_cairo_write_func_t (gpointer self, guchar* data, int data_length1); +static void ps_writer_finalize (PsWriter* obj); + + +static void _page_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (page_unref (var), NULL)); +} + + +static void _g_list_free__page_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _page_unref0_, NULL); + g_list_free (self); +} + + +Book* book_construct (GType object_type) { + Book* self = NULL; + self = (Book*) g_type_create_instance (object_type); + return self; +} + + +Book* book_new (void) { + return book_construct (TYPE_BOOK); +} + + +void book_clear (Book* self) { + g_return_if_fail (self != NULL); + __g_list_free__page_unref0_0 (self->priv->pages); + self->priv->pages = NULL; + g_signal_emit_by_name (self, "cleared"); +} + + +static void book_page_changed_cb (Book* self, Page* page) { + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + book_set_needs_saving (self, TRUE); +} + + +static void _book_page_changed_cb_page_pixels_changed (Page* _sender, gpointer self) { + book_page_changed_cb (self, _sender); +} + + +static void _book_page_changed_cb_page_crop_changed (Page* _sender, gpointer self) { + book_page_changed_cb (self, _sender); +} + + +static gpointer _page_ref0 (gpointer self) { + return self ? page_ref (self) : NULL; +} + + +Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction) { + Page* result = NULL; + Page* _tmp0_ = NULL; + Page* page; + Page* _tmp1_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = page_new (width, height, dpi, scan_direction); + page = _tmp0_; + g_signal_connect (page, "pixels-changed", (GCallback) _book_page_changed_cb_page_pixels_changed, self); + g_signal_connect (page, "crop-changed", (GCallback) _book_page_changed_cb_page_crop_changed, self); + _tmp1_ = _page_ref0 (page); + self->priv->pages = g_list_append (self->priv->pages, _tmp1_); + g_signal_emit_by_name (self, "page-added", page); + book_set_needs_saving (self, TRUE); + result = page; + return result; +} + + +void book_move_page (Book* self, Page* page, guint location) { + Page* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + self->priv->pages = g_list_remove (self->priv->pages, page); + _tmp0_ = _page_ref0 (page); + self->priv->pages = g_list_insert (self->priv->pages, _tmp0_, (gint) location); + g_signal_emit_by_name (self, "reordered"); + book_set_needs_saving (self, TRUE); +} + + +void book_delete_page (Book* self, Page* page) { + guint _tmp0_; + guint _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + g_signal_parse_name ("pixels-changed", TYPE_PAGE, &_tmp0_, NULL, FALSE); + g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp0_, 0, NULL, (GCallback) _book_page_changed_cb_page_pixels_changed, self); + g_signal_parse_name ("crop-changed", TYPE_PAGE, &_tmp1_, NULL, FALSE); + g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp1_, 0, NULL, (GCallback) _book_page_changed_cb_page_crop_changed, self); + g_signal_emit_by_name (self, "page-removed", page); + self->priv->pages = g_list_remove (self->priv->pages, page); + book_set_needs_saving (self, TRUE); +} + + +guint book_get_n_pages (Book* self) { + guint result = 0U; + guint _tmp0_; + g_return_val_if_fail (self != NULL, 0U); + _tmp0_ = g_list_length (self->priv->pages); + result = _tmp0_; + return result; +} + + +Page* book_get_page (Book* self, gint page_number) { + Page* result = NULL; + gconstpointer _tmp1_ = NULL; + Page* _tmp2_; + g_return_val_if_fail (self != NULL, NULL); + if (page_number < 0) { + guint _tmp0_; + _tmp0_ = g_list_length (self->priv->pages); + page_number = ((gint) _tmp0_) + page_number; + } + _tmp1_ = g_list_nth_data (self->priv->pages, (guint) page_number); + _tmp2_ = _page_ref0 ((Page*) _tmp1_); + result = _tmp2_; + return result; +} + + +guint book_get_page_index (Book* self, Page* page) { + guint result = 0U; + gint _tmp0_; + g_return_val_if_fail (self != NULL, 0U); + g_return_val_if_fail (page != NULL, 0U); + _tmp0_ = g_list_index (self->priv->pages, page); + result = (guint) _tmp0_; + return result; +} + + +static gint string_last_index_of_char (const gchar* self, gunichar c, gint start_index) { + gint result = 0; + gchar* _tmp0_ = NULL; + gchar* _result_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = g_utf8_strrchr (((gchar*) self) + start_index, (gssize) (-1), c); + _result_ = _tmp0_; + if (_result_ != NULL) { + result = (gint) (_result_ - ((gchar*) self)); + return result; + } else { + result = -1; + return result; + } +} + + +static gchar* string_slice (const gchar* self, glong start, glong end) { + gchar* result = NULL; + gint _tmp0_; + glong string_length; + gboolean _tmp1_ = FALSE; + gboolean _tmp2_ = FALSE; + gchar* _tmp3_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = strlen (self); + string_length = (glong) _tmp0_; + if (start < ((glong) 0)) { + start = string_length + start; + } + if (end < ((glong) 0)) { + end = string_length + end; + } + if (start >= ((glong) 0)) { + _tmp1_ = start <= string_length; + } else { + _tmp1_ = FALSE; + } + g_return_val_if_fail (_tmp1_, NULL); + if (end >= ((glong) 0)) { + _tmp2_ = end <= string_length; + } else { + _tmp2_ = FALSE; + } + g_return_val_if_fail (_tmp2_, NULL); + g_return_val_if_fail (start <= end, NULL); + _tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start)); + result = _tmp3_; + return result; +} + + +static GFile* book_make_indexed_file (Book* self, const gchar* uri, gint i) { + GFile* result = NULL; + gchar* _tmp1_ = NULL; + gchar* basename; + gchar* _tmp2_; + gchar* prefix; + gchar* _tmp3_; + gchar* suffix; + gint _tmp4_; + gint extension_index; + gchar* _tmp10_ = NULL; + gchar* _tmp11_; + GFile* _tmp12_ = NULL; + GFile* _tmp13_; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (uri != NULL, NULL); + if (i == 0) { + GFile* _tmp0_ = NULL; + _tmp0_ = g_file_new_for_uri (uri); + result = _tmp0_; + return result; + } + _tmp1_ = g_path_get_basename (uri); + basename = _tmp1_; + _tmp2_ = g_strdup (uri); + prefix = _tmp2_; + _tmp3_ = g_strdup (""); + suffix = _tmp3_; + _tmp4_ = string_last_index_of_char (basename, (gunichar) '.', 0); + extension_index = _tmp4_; + if (extension_index >= 0) { + gint _tmp5_; + gchar* _tmp6_ = NULL; + gint _tmp7_; + gint _tmp8_; + gchar* _tmp9_ = NULL; + _tmp5_ = strlen (basename); + _tmp6_ = string_slice (basename, (glong) extension_index, (glong) _tmp5_); + _g_free0 (suffix); + suffix = _tmp6_; + _tmp7_ = strlen (uri); + _tmp8_ = strlen (suffix); + _tmp9_ = string_slice (uri, (glong) 0, (glong) (_tmp7_ - _tmp8_)); + _g_free0 (prefix); + prefix = _tmp9_; + } + _tmp10_ = g_strdup_printf ("%s-%d%s", prefix, i, suffix); + _tmp11_ = _tmp10_; + _tmp12_ = g_file_new_for_uri (_tmp11_); + _tmp13_ = _tmp12_; + _g_free0 (_tmp11_); + result = _tmp13_; + _g_free0 (suffix); + _g_free0 (prefix); + _g_free0 (basename); + return result; +} + + +static void book_save_multi_file (Book* self, const gchar* type, GFile* file, GError** error) { + gint i; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (type != NULL); + g_return_if_fail (file != NULL); + i = 0; + { + GList* page_collection = NULL; + GList* page_it = NULL; + page_collection = self->priv->pages; + for (page_it = page_collection; page_it != NULL; page_it = page_it->next) { + Page* _tmp0_; + Page* page = NULL; + _tmp0_ = _page_ref0 ((Page*) page_it->data); + page = _tmp0_; + { + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + GFile* _tmp3_ = NULL; + GFile* _tmp4_; + _tmp1_ = g_file_get_uri (file); + _tmp2_ = _tmp1_; + _tmp3_ = book_make_indexed_file (self, _tmp2_, i); + _tmp4_ = _tmp3_; + page_save (page, type, _tmp4_, &_inner_error_); + _g_object_unref0 (_tmp4_); + _g_free0 (_tmp2_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + _page_unref0 (page); + return; + } + i++; + _page_unref0 (page); + } + } + } +} + + +static void book_save_ps_pdf_surface (Book* self, cairo_surface_t* surface, GdkPixbuf* image, gdouble dpi) { + cairo_t* _tmp0_ = NULL; + cairo_t* context; + cairo_pattern_t* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (surface != NULL); + g_return_if_fail (image != NULL); + _tmp0_ = cairo_create (surface); + context = _tmp0_; + cairo_scale (context, 72.0 / dpi, 72.0 / dpi); + gdk_cairo_set_source_pixbuf (context, image, (gdouble) 0, (gdouble) 0); + _tmp1_ = cairo_get_source (context); + cairo_pattern_set_filter (_tmp1_, CAIRO_FILTER_BEST); + cairo_paint (context); + _cairo_destroy0 (context); +} + + +static gpointer _cairo_surface_reference0 (gpointer self) { + return self ? cairo_surface_reference (self) : NULL; +} + + +static void book_save_ps (Book* self, GFile* file, GError** error) { + GFileOutputStream* _tmp0_ = NULL; + GFileOutputStream* stream; + PsWriter* _tmp1_ = NULL; + PsWriter* writer; + cairo_surface_t* _tmp2_; + cairo_surface_t* surface; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &_inner_error_); + stream = _tmp0_; + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + _tmp1_ = ps_writer_new (stream); + writer = _tmp1_; + _tmp2_ = _cairo_surface_reference0 (writer->surface); + surface = _tmp2_; + { + GList* page_collection = NULL; + GList* page_it = NULL; + page_collection = self->priv->pages; + for (page_it = page_collection; page_it != NULL; page_it = page_it->next) { + Page* _tmp3_; + Page* page = NULL; + _tmp3_ = _page_ref0 ((Page*) page_it->data); + page = _tmp3_; + { + GdkPixbuf* _tmp4_ = NULL; + GdkPixbuf* image; + gint _tmp5_; + gint _tmp6_; + gdouble width; + gint _tmp7_; + gint _tmp8_; + gdouble height; + gint _tmp9_; + _tmp4_ = page_get_image (page, TRUE); + image = _tmp4_; + _tmp5_ = gdk_pixbuf_get_width (image); + _tmp6_ = page_get_dpi (page); + width = (_tmp5_ * 72.0) / _tmp6_; + _tmp7_ = gdk_pixbuf_get_height (image); + _tmp8_ = page_get_dpi (page); + height = (_tmp7_ * 72.0) / _tmp8_; + cairo_ps_surface_set_size (surface, width, height); + _tmp9_ = page_get_dpi (page); + book_save_ps_pdf_surface (self, surface, image, (gdouble) _tmp9_); + cairo_surface_show_page (surface); + _g_object_unref0 (image); + _page_unref0 (page); + } + } + } + _cairo_surface_destroy0 (surface); + _ps_writer_unref0 (writer); + _g_object_unref0 (stream); +} + + +static guint8* book_compress_zlib (Book* self, guint8* data, int data_length1, int* result_length1) { + guint8* result = NULL; + z_stream stream = {0}; + guint8* _tmp0_ = NULL; + guint8* out_data; + gint out_data_length1; + gint _out_data_size_; + guint n_written; + gint _tmp3_; + guint8* _tmp4_; + g_return_val_if_fail (self != NULL, NULL); + deflateInit (&stream, (gint) Z_BEST_COMPRESSION); + _tmp0_ = g_new0 (guint8, data_length1); + out_data = _tmp0_; + out_data_length1 = data_length1; + _out_data_size_ = out_data_length1; + stream.next_in = data; + stream.avail_in = data_length1; + stream.next_out = out_data; + stream.avail_out = out_data_length1; + while (TRUE) { + gint _tmp1_; + if (!(stream.avail_in > ((guint) 0))) { + break; + } + _tmp1_ = deflate (&stream, (gint) Z_FINISH); + if (_tmp1_ == ((gint) Z_STREAM_ERROR)) { + break; + } + } + if (stream.avail_in > ((guint) 0)) { + guint8* _tmp2_; + _tmp2_ = NULL; + if (result_length1) { + *result_length1 = 0; + } + result = _tmp2_; + out_data = (g_free (out_data), NULL); + deflateEnd (&stream); + return result; + } + n_written = data_length1 - stream.avail_out; + _tmp3_ = (gint) n_written; + out_data = g_renew (guint8, out_data, (gint) n_written); + (_tmp3_ > out_data_length1) ? memset (out_data + out_data_length1, 0, sizeof (guint8) * (_tmp3_ - out_data_length1)) : NULL; + out_data_length1 = _tmp3_; + _out_data_size_ = _tmp3_; + _tmp4_ = out_data; + if (result_length1) { + *result_length1 = out_data_length1; + } + result = _tmp4_; + deflateEnd (&stream); + return result; +} + + +static void book_jpeg_init_cb (struct jpeg_compress_struct* info) { +} + + +static gboolean book_jpeg_empty_cb (struct jpeg_compress_struct* info) { + gboolean result = FALSE; + result = TRUE; + return result; +} + + +static void book_jpeg_term_cb (struct jpeg_compress_struct* info) { +} + + +static void _book_jpeg_init_cb_jpeg_initdestinationfunc (struct jpeg_compress_struct* cinfo) { + book_jpeg_init_cb (cinfo); +} + + +static gboolean _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc (struct jpeg_compress_struct* cinfo) { + gboolean result; + result = book_jpeg_empty_cb (cinfo); + return result; +} + + +static void _book_jpeg_term_cb_jpeg_termdestinationfunc (struct jpeg_compress_struct* cinfo) { + book_jpeg_term_cb (cinfo); +} + + +static guint8* book_compress_jpeg (Book* self, GdkPixbuf* image, gsize* n_written, int* result_length1) { + gsize _n_written = 0UL; + guint8* result = NULL; + struct jpeg_compress_struct info = {0}; + struct jpeg_error_mgr jerr = {0}; + struct jpeg_destination_mgr dest_mgr = {0}; + struct jpeg_error_mgr* _tmp0_ = NULL; + gint _tmp1_; + gint _tmp2_; + gint max_length; + guint8* _tmp3_ = NULL; + guint8* data; + gint data_length1; + gint _data_size_; + guint8* _tmp4_ = NULL; + guint8* pixels; + gint pixels_length1; + gint _pixels_size_; + guint8* _tmp7_; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (image != NULL, NULL); + memset (&info, 0, sizeof (struct jpeg_compress_struct)); + memset (&jerr, 0, sizeof (struct jpeg_error_mgr)); + memset (&dest_mgr, 0, sizeof (struct jpeg_destination_mgr)); + _tmp0_ = jpeg_std_error (&jerr); + info.err = _tmp0_; + jpeg_create_compress (&info); + _tmp1_ = gdk_pixbuf_get_width (image); + info.image_width = _tmp1_; + _tmp2_ = gdk_pixbuf_get_height (image); + info.image_height = _tmp2_; + info.input_components = 3; + info.in_color_space = JCS_RGB; + jpeg_set_defaults (&info); + max_length = (info.image_width * info.image_height) * info.input_components; + _tmp3_ = g_new0 (guint8, max_length); + data = _tmp3_; + data_length1 = max_length; + _data_size_ = data_length1; + dest_mgr.next_output_byte = data; + dest_mgr.free_in_buffer = max_length; + dest_mgr.init_destination = _book_jpeg_init_cb_jpeg_initdestinationfunc; + dest_mgr.empty_output_buffer = _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc; + dest_mgr.term_destination = _book_jpeg_term_cb_jpeg_termdestinationfunc; + info.dest = &dest_mgr; + jpeg_start_compress (&info, TRUE); + _tmp4_ = gdk_pixbuf_get_pixels (image); + pixels = _tmp4_; + pixels_length1 = -1; + _pixels_size_ = pixels_length1; + { + gint r; + r = 0; + { + gboolean _tmp5_; + _tmp5_ = TRUE; + while (TRUE) { + guint8* row[1] = {0}; + gint _tmp6_; + if (!_tmp5_) { + r++; + } + _tmp5_ = FALSE; + if (!(r < info.image_height)) { + break; + } + _tmp6_ = gdk_pixbuf_get_rowstride (image); + row[0] = ((guint8*) pixels) + (r * _tmp6_); + jpeg_write_scanlines (&info, row, 1); + } + } + } + jpeg_finish_compress (&info); + _n_written = (gsize) (max_length - dest_mgr.free_in_buffer); + _tmp7_ = data; + if (result_length1) { + *result_length1 = data_length1; + } + result = _tmp7_; + jpeg_destroy_compress (&info); + if (n_written) { + *n_written = _n_written; + } + return result; +} + + +static guint8* _vala_array_dup1 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static guint8* _vala_array_dup2 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static void book_save_pdf (Book* self, GFile* file, GError** error) { + GFileOutputStream* _tmp0_ = NULL; + GFileOutputStream* stream; + PDFWriter* _tmp1_ = NULL; + PDFWriter* writer; + guint _tmp2_; + guint catalog_number; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + gchar* _tmp5_ = NULL; + gchar* _tmp6_; + guint _tmp7_; + guint pages_number; + gchar* _tmp8_ = NULL; + gchar* _tmp9_; + guint _tmp14_; + gchar* _tmp15_ = NULL; + gchar* _tmp16_; + guint _tmp100_; + guint info_number; + gchar* _tmp101_ = NULL; + gchar* _tmp102_; + gchar* _tmp103_ = NULL; + gchar* _tmp104_; + gsize xref_offset; + guint _tmp105_; + gchar* _tmp106_ = NULL; + gchar* _tmp107_; + guint _tmp110_; + gchar* _tmp111_ = NULL; + gchar* _tmp112_; + gchar* _tmp113_ = NULL; + gchar* _tmp114_; + gchar* _tmp115_ = NULL; + gchar* _tmp116_; + gchar* _tmp117_ = NULL; + gchar* _tmp118_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &_inner_error_); + stream = _tmp0_; + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + _tmp1_ = pdf_writer_new (stream); + writer = _tmp1_; + pdf_writer_write_string (writer, "%%PDF-1.3\n"); + pdf_writer_write_string (writer, "%%\xe2\xe3\xcf\xd3\n"); + _tmp2_ = pdf_writer_start_object (writer); + catalog_number = _tmp2_; + _tmp3_ = g_strdup_printf ("%u 0 obj\n", catalog_number); + _tmp4_ = _tmp3_; + pdf_writer_write_string (writer, _tmp4_); + _g_free0 (_tmp4_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /Catalog\n"); + _tmp5_ = g_strdup_printf ("/Pages %u 0 R\n", catalog_number + 1); + _tmp6_ = _tmp5_; + pdf_writer_write_string (writer, _tmp6_); + _g_free0 (_tmp6_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + pdf_writer_write_string (writer, "\n"); + _tmp7_ = pdf_writer_start_object (writer); + pages_number = _tmp7_; + _tmp8_ = g_strdup_printf ("%u 0 obj\n", pages_number); + _tmp9_ = _tmp8_; + pdf_writer_write_string (writer, _tmp9_); + _g_free0 (_tmp9_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /Pages\n"); + pdf_writer_write_string (writer, "/Kids ["); + { + gint i; + i = 0; + { + gboolean _tmp10_; + _tmp10_ = TRUE; + while (TRUE) { + guint _tmp11_; + gchar* _tmp12_ = NULL; + gchar* _tmp13_; + if (!_tmp10_) { + i++; + } + _tmp10_ = FALSE; + _tmp11_ = book_get_n_pages (self); + if (!(((guint) i) < _tmp11_)) { + break; + } + _tmp12_ = g_strdup_printf (" %u 0 R", (pages_number + 1) + (i * 3)); + _tmp13_ = _tmp12_; + pdf_writer_write_string (writer, _tmp13_); + _g_free0 (_tmp13_); + } + } + } + pdf_writer_write_string (writer, " ]\n"); + _tmp14_ = book_get_n_pages (self); + _tmp15_ = g_strdup_printf ("/Count %u\n", _tmp14_); + _tmp16_ = _tmp15_; + pdf_writer_write_string (writer, _tmp16_); + _g_free0 (_tmp16_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + { + gint i; + i = 0; + { + gboolean _tmp17_; + _tmp17_ = TRUE; + while (TRUE) { + guint _tmp18_; + Page* _tmp19_ = NULL; + Page* page; + GdkPixbuf* _tmp20_ = NULL; + GdkPixbuf* image; + gint _tmp21_; + gint width; + gint _tmp22_; + gint height; + guint8* _tmp23_ = NULL; + guint8* pixels; + gint pixels_length1; + gint _pixels_size_; + gint _tmp24_; + gdouble page_width; + gint _tmp25_; + gdouble page_height; + gint depth; + gchar* _tmp26_; + gchar* color_space; + gchar* filter; + gchar* _tmp27_ = NULL; + gchar* width_buffer; + gint width_buffer_length1; + gint _width_buffer_size_; + gchar* _tmp28_ = NULL; + gchar* height_buffer; + gint height_buffer_length1; + gint _height_buffer_size_; + guint8* data = NULL; + gint data_length1 = 0; + gint _data_size_ = 0; + gboolean _tmp29_; + gint _tmp52_; + guint8* _tmp53_ = NULL; + guint8* compressed_data; + gint compressed_data_length1; + gint _compressed_data_size_; + guint _tmp63_; + guint number; + gchar* _tmp64_ = NULL; + gchar* _tmp65_; + gchar* _tmp66_ = NULL; + gchar* _tmp67_; + gchar* _tmp68_ = NULL; + gchar* _tmp69_; + const gchar* _tmp70_ = NULL; + const gchar* _tmp71_ = NULL; + gchar* _tmp72_ = NULL; + gchar* _tmp73_; + gchar* _tmp74_ = NULL; + gchar* _tmp75_; + guint _tmp76_; + gchar* _tmp77_ = NULL; + gchar* _tmp78_; + gchar* _tmp79_ = NULL; + gchar* _tmp80_; + gchar* _tmp81_ = NULL; + gchar* _tmp82_; + gchar* _tmp83_ = NULL; + gchar* _tmp84_; + gchar* _tmp85_ = NULL; + gchar* _tmp86_; + gchar* _tmp87_ = NULL; + gchar* _tmp88_; + const gchar* _tmp91_ = NULL; + const gchar* _tmp92_ = NULL; + gchar* _tmp93_ = NULL; + gchar* command; + guint _tmp94_; + gchar* _tmp95_ = NULL; + gchar* _tmp96_; + gint _tmp97_; + gchar* _tmp98_ = NULL; + gchar* _tmp99_; + if (!_tmp17_) { + i++; + } + _tmp17_ = FALSE; + _tmp18_ = book_get_n_pages (self); + if (!(((guint) i) < _tmp18_)) { + break; + } + _tmp19_ = book_get_page (self, i); + page = _tmp19_; + _tmp20_ = page_get_image (page, TRUE); + image = _tmp20_; + _tmp21_ = gdk_pixbuf_get_width (image); + width = _tmp21_; + _tmp22_ = gdk_pixbuf_get_height (image); + height = _tmp22_; + _tmp23_ = gdk_pixbuf_get_pixels (image); + pixels = _tmp23_; + pixels_length1 = -1; + _pixels_size_ = pixels_length1; + _tmp24_ = page_get_dpi (page); + page_width = (width * 72.0) / _tmp24_; + _tmp25_ = page_get_dpi (page); + page_height = (height * 72.0) / _tmp25_; + depth = 8; + _tmp26_ = g_strdup ("DeviceRGB"); + color_space = _tmp26_; + filter = NULL; + _tmp27_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE); + width_buffer = _tmp27_; + width_buffer_length1 = G_ASCII_DTOSTR_BUF_SIZE; + _width_buffer_size_ = width_buffer_length1; + _tmp28_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE); + height_buffer = _tmp28_; + height_buffer_length1 = G_ASCII_DTOSTR_BUF_SIZE; + _height_buffer_size_ = height_buffer_length1; + _tmp29_ = page_is_color (page); + if (_tmp29_) { + gchar* _tmp30_; + gint data_length; + guint8* _tmp31_ = NULL; + depth = 8; + _tmp30_ = g_strdup ("DeviceRGB"); + _g_free0 (color_space); + color_space = _tmp30_; + data_length = ((height * width) * 3) + 1; + _tmp31_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp31_; + data_length1 = data_length; + _data_size_ = data_length1; + { + gint row; + row = 0; + { + gboolean _tmp32_; + _tmp32_ = TRUE; + while (TRUE) { + gint _tmp33_; + gint in_offset; + gint out_offset; + if (!_tmp32_) { + row++; + } + _tmp32_ = FALSE; + if (!(row < height)) { + break; + } + _tmp33_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp33_; + out_offset = (row * width) * 3; + { + gint x; + x = 0; + { + gboolean _tmp34_; + _tmp34_ = TRUE; + while (TRUE) { + gint in_o; + gint out_o; + if (!_tmp34_) { + x++; + } + _tmp34_ = FALSE; + if (!(x < width)) { + break; + } + in_o = in_offset + (x * 3); + out_o = out_offset + (x * 3); + data[out_o] = pixels[in_o]; + data[out_o + 1] = pixels[in_o + 1]; + data[out_o + 2] = pixels[in_o + 2]; + } + } + } + } + } + } + } else { + gint _tmp35_; + _tmp35_ = page_get_depth (page); + if (_tmp35_ == 2) { + gint shift_count; + gchar* _tmp36_; + gint data_length; + guint8* _tmp37_ = NULL; + gint offset; + shift_count = 6; + depth = 2; + _tmp36_ = g_strdup ("DeviceGray"); + _g_free0 (color_space); + color_space = _tmp36_; + data_length = height * (((width * 2) + 7) / 8); + _tmp37_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp37_; + data_length1 = data_length; + _data_size_ = data_length1; + offset = 0; + data[offset] = (guint8) 0; + { + gint row; + row = 0; + { + gboolean _tmp38_; + _tmp38_ = TRUE; + while (TRUE) { + gint _tmp39_; + gint in_offset; + if (!_tmp38_) { + row++; + } + _tmp38_ = FALSE; + if (!(row < height)) { + break; + } + if (shift_count != 6) { + offset++; + data[offset] = (guint8) 0; + shift_count = 6; + } + _tmp39_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp39_; + { + gint x; + x = 0; + { + gboolean _tmp40_; + _tmp40_ = TRUE; + while (TRUE) { + guint8 p; + if (!_tmp40_) { + x++; + } + _tmp40_ = FALSE; + if (!(x < width)) { + break; + } + p = pixels[in_offset + (x * 3)]; + if (((gint) p) >= 192) { + data[offset] |= (guint8) (3 << shift_count); + } else { + if (((gint) p) >= 128) { + data[offset] |= (guint8) (2 << shift_count); + } else { + if (((gint) p) >= 64) { + data[offset] |= (guint8) (1 << shift_count); + } + } + } + if (shift_count == 0) { + offset++; + data[offset] = (guint8) 0; + shift_count = 6; + } else { + shift_count = shift_count - 2; + } + } + } + } + } + } + } + } else { + gint _tmp41_; + _tmp41_ = page_get_depth (page); + if (_tmp41_ == 1) { + gint mask; + gchar* _tmp42_; + gint data_length; + guint8* _tmp43_ = NULL; + gint offset; + mask = 0x80; + depth = 1; + _tmp42_ = g_strdup ("DeviceGray"); + _g_free0 (color_space); + color_space = _tmp42_; + data_length = height * ((width + 7) / 8); + _tmp43_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp43_; + data_length1 = data_length; + _data_size_ = data_length1; + offset = 0; + data[offset] = (guint8) 0; + { + gint row; + row = 0; + { + gboolean _tmp44_; + _tmp44_ = TRUE; + while (TRUE) { + gint _tmp45_; + gint in_offset; + if (!_tmp44_) { + row++; + } + _tmp44_ = FALSE; + if (!(row < height)) { + break; + } + if (mask != 0x80) { + offset++; + data[offset] = (guint8) 0; + mask = 0x80; + } + _tmp45_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp45_; + { + gint x; + x = 0; + { + gboolean _tmp46_; + _tmp46_ = TRUE; + while (TRUE) { + if (!_tmp46_) { + x++; + } + _tmp46_ = FALSE; + if (!(x < width)) { + break; + } + if (((gint) pixels[in_offset + (x * 3)]) != 0) { + data[offset] |= (guint8) mask; + } + mask = mask >> 1; + if (mask == 0) { + offset++; + data[offset] = (guint8) 0; + mask = 0x80; + } + } + } + } + } + } + } + } else { + gchar* _tmp47_; + gint data_length; + guint8* _tmp48_ = NULL; + depth = 8; + _tmp47_ = g_strdup ("DeviceGray"); + _g_free0 (color_space); + color_space = _tmp47_; + data_length = (height * width) + 1; + _tmp48_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp48_; + data_length1 = data_length; + _data_size_ = data_length1; + { + gint row; + row = 0; + { + gboolean _tmp49_; + _tmp49_ = TRUE; + while (TRUE) { + gint _tmp50_; + gint in_offset; + gint out_offset; + if (!_tmp49_) { + row++; + } + _tmp49_ = FALSE; + if (!(row < height)) { + break; + } + _tmp50_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp50_; + out_offset = row * width; + { + gint x; + x = 0; + { + gboolean _tmp51_; + _tmp51_ = TRUE; + while (TRUE) { + if (!_tmp51_) { + x++; + } + _tmp51_ = FALSE; + if (!(x < width)) { + break; + } + data[out_offset + x] = pixels[in_offset + (x * 3)]; + } + } + } + } + } + } + } + } + } + _tmp53_ = book_compress_zlib (self, data, data_length1, &_tmp52_); + compressed_data = _tmp53_; + compressed_data_length1 = _tmp52_; + _compressed_data_size_ = compressed_data_length1; + if (compressed_data != NULL) { + if (depth > 1) { + gsize jpeg_length = 0UL; + gsize _tmp54_; + gint _tmp55_; + guint8* _tmp56_ = NULL; + guint8* jpeg_data; + gint jpeg_data_length1; + gint _jpeg_data_size_; + _tmp56_ = book_compress_jpeg (self, image, &_tmp54_, &_tmp55_); + jpeg_length = _tmp54_; + jpeg_data = _tmp56_; + jpeg_data_length1 = _tmp55_; + _jpeg_data_size_ = jpeg_data_length1; + if (jpeg_length < ((gsize) compressed_data_length1)) { + gchar* _tmp57_; + guint8* _tmp58_; + guint8* _tmp59_; + _tmp57_ = g_strdup ("DCTDecode"); + _g_free0 (filter); + filter = _tmp57_; + _tmp59_ = (_tmp58_ = jpeg_data, (_tmp58_ == NULL) ? ((gpointer) _tmp58_) : _vala_array_dup1 (_tmp58_, jpeg_data_length1)); + data = (g_free (data), NULL); + data = _tmp59_; + data_length1 = jpeg_data_length1; + _data_size_ = data_length1; + } + jpeg_data = (g_free (jpeg_data), NULL); + } + if (filter == NULL) { + gchar* _tmp60_; + guint8* _tmp61_; + guint8* _tmp62_; + _tmp60_ = g_strdup ("FlateDecode"); + _g_free0 (filter); + filter = _tmp60_; + _tmp62_ = (_tmp61_ = compressed_data, (_tmp61_ == NULL) ? ((gpointer) _tmp61_) : _vala_array_dup2 (_tmp61_, compressed_data_length1)); + data = (g_free (data), NULL); + data = _tmp62_; + data_length1 = compressed_data_length1; + _data_size_ = data_length1; + } + } + pdf_writer_write_string (writer, "\n"); + _tmp63_ = pdf_writer_start_object (writer); + number = _tmp63_; + _tmp64_ = g_strdup_printf ("%u 0 obj\n", number); + _tmp65_ = _tmp64_; + pdf_writer_write_string (writer, _tmp65_); + _g_free0 (_tmp65_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /Page\n"); + _tmp66_ = g_strdup_printf ("/Parent %u 0 R\n", pages_number); + _tmp67_ = _tmp66_; + pdf_writer_write_string (writer, _tmp67_); + _g_free0 (_tmp67_); + _tmp68_ = g_strdup_printf ("/Resources << /XObject << /Im%d %u 0 R >> >>\n", i, number + 1); + _tmp69_ = _tmp68_; + pdf_writer_write_string (writer, _tmp69_); + _g_free0 (_tmp69_); + _tmp70_ = g_ascii_formatd (width_buffer, width_buffer_length1, "%.2f", page_width); + _tmp71_ = g_ascii_formatd (height_buffer, height_buffer_length1, "%.2f", page_height); + _tmp72_ = g_strdup_printf ("/MediaBox [ 0 0 %s %s ]\n", _tmp70_, _tmp71_); + _tmp73_ = _tmp72_; + pdf_writer_write_string (writer, _tmp73_); + _g_free0 (_tmp73_); + _tmp74_ = g_strdup_printf ("/Contents %u 0 R\n", number + 2); + _tmp75_ = _tmp74_; + pdf_writer_write_string (writer, _tmp75_); + _g_free0 (_tmp75_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + pdf_writer_write_string (writer, "\n"); + _tmp76_ = pdf_writer_start_object (writer); + number = _tmp76_; + _tmp77_ = g_strdup_printf ("%u 0 obj\n", number); + _tmp78_ = _tmp77_; + pdf_writer_write_string (writer, _tmp78_); + _g_free0 (_tmp78_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /XObject\n"); + pdf_writer_write_string (writer, "/Subtype /Image\n"); + _tmp79_ = g_strdup_printf ("/Width %d\n", width); + _tmp80_ = _tmp79_; + pdf_writer_write_string (writer, _tmp80_); + _g_free0 (_tmp80_); + _tmp81_ = g_strdup_printf ("/Height %d\n", height); + _tmp82_ = _tmp81_; + pdf_writer_write_string (writer, _tmp82_); + _g_free0 (_tmp82_); + _tmp83_ = g_strdup_printf ("/ColorSpace /%s\n", color_space); + _tmp84_ = _tmp83_; + pdf_writer_write_string (writer, _tmp84_); + _g_free0 (_tmp84_); + _tmp85_ = g_strdup_printf ("/BitsPerComponent %d\n", depth); + _tmp86_ = _tmp85_; + pdf_writer_write_string (writer, _tmp86_); + _g_free0 (_tmp86_); + _tmp87_ = g_strdup_printf ("/Length %d\n", data_length1); + _tmp88_ = _tmp87_; + pdf_writer_write_string (writer, _tmp88_); + _g_free0 (_tmp88_); + if (filter != NULL) { + gchar* _tmp89_ = NULL; + gchar* _tmp90_; + _tmp89_ = g_strdup_printf ("/Filter /%s\n", filter); + _tmp90_ = _tmp89_; + pdf_writer_write_string (writer, _tmp90_); + _g_free0 (_tmp90_); + } + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "stream\n"); + pdf_writer_write (writer, data, data_length1); + pdf_writer_write_string (writer, "\n"); + pdf_writer_write_string (writer, "endstream\n"); + pdf_writer_write_string (writer, "endobj\n"); + _tmp91_ = g_ascii_formatd (width_buffer, width_buffer_length1, "%f", page_width); + _tmp92_ = g_ascii_formatd (height_buffer, height_buffer_length1, "%f", page_height); + _tmp93_ = g_strdup_printf ("q\n%s 0 0 %s 0 0 cm\n/Im%d Do\nQ", _tmp91_, _tmp92_, i); + command = _tmp93_; + pdf_writer_write_string (writer, "\n"); + _tmp94_ = pdf_writer_start_object (writer); + number = _tmp94_; + _tmp95_ = g_strdup_printf ("%u 0 obj\n", number); + _tmp96_ = _tmp95_; + pdf_writer_write_string (writer, _tmp96_); + _g_free0 (_tmp96_); + pdf_writer_write_string (writer, "<<\n"); + _tmp97_ = strlen (command); + _tmp98_ = g_strdup_printf ("/Length %d\n", _tmp97_ + 1); + _tmp99_ = _tmp98_; + pdf_writer_write_string (writer, _tmp99_); + _g_free0 (_tmp99_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "stream\n"); + pdf_writer_write_string (writer, command); + pdf_writer_write_string (writer, "\n"); + pdf_writer_write_string (writer, "endstream\n"); + pdf_writer_write_string (writer, "endobj\n"); + _g_free0 (command); + compressed_data = (g_free (compressed_data), NULL); + data = (g_free (data), NULL); + height_buffer = (g_free (height_buffer), NULL); + width_buffer = (g_free (width_buffer), NULL); + _g_free0 (filter); + _g_free0 (color_space); + _g_object_unref0 (image); + _page_unref0 (page); + } + } + } + pdf_writer_write_string (writer, "\n"); + _tmp100_ = pdf_writer_start_object (writer); + info_number = _tmp100_; + _tmp101_ = g_strdup_printf ("%u 0 obj\n", info_number); + _tmp102_ = _tmp101_; + pdf_writer_write_string (writer, _tmp102_); + _g_free0 (_tmp102_); + pdf_writer_write_string (writer, "<<\n"); + _tmp103_ = g_strdup_printf ("/Creator (Simple Scan %s)\n", VERSION); + _tmp104_ = _tmp103_; + pdf_writer_write_string (writer, _tmp104_); + _g_free0 (_tmp104_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + xref_offset = writer->offset; + pdf_writer_write_string (writer, "xref\n"); + _tmp105_ = g_list_length (writer->object_offsets); + _tmp106_ = g_strdup_printf ("1 %zu\n", (gsize) _tmp105_); + _tmp107_ = _tmp106_; + pdf_writer_write_string (writer, _tmp107_); + _g_free0 (_tmp107_); + { + GList* offset_collection = NULL; + GList* offset_it = NULL; + offset_collection = writer->object_offsets; + for (offset_it = offset_collection; offset_it != NULL; offset_it = offset_it->next) { + guint offset = 0U; + offset = GPOINTER_TO_UINT (offset_it->data); + { + gchar* _tmp108_ = NULL; + gchar* _tmp109_; + _tmp108_ = g_strdup_printf ("%010zu 0000 n\n", (gsize) offset); + _tmp109_ = _tmp108_; + pdf_writer_write_string (writer, _tmp109_); + _g_free0 (_tmp109_); + } + } + } + pdf_writer_write_string (writer, "trailer\n"); + pdf_writer_write_string (writer, "<<\n"); + _tmp110_ = g_list_length (writer->object_offsets); + _tmp111_ = g_strdup_printf ("/Size %zu\n", (gsize) _tmp110_); + _tmp112_ = _tmp111_; + pdf_writer_write_string (writer, _tmp112_); + _g_free0 (_tmp112_); + _tmp113_ = g_strdup_printf ("/Info %u 0 R\n", info_number); + _tmp114_ = _tmp113_; + pdf_writer_write_string (writer, _tmp114_); + _g_free0 (_tmp114_); + _tmp115_ = g_strdup_printf ("/Root %u 0 R\n", catalog_number); + _tmp116_ = _tmp115_; + pdf_writer_write_string (writer, _tmp116_); + _g_free0 (_tmp116_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "startxref\n"); + _tmp117_ = g_strdup_printf ("%zu\n", xref_offset); + _tmp118_ = _tmp117_; + pdf_writer_write_string (writer, _tmp118_); + _g_free0 (_tmp118_); + pdf_writer_write_string (writer, "%%%%EOF\n"); + _pdf_writer_unref0 (writer); + _g_object_unref0 (stream); +} + + +void book_save (Book* self, const gchar* type, GFile* file, GError** error) { + gint _tmp0_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (type != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_strcmp0 (type, "jpeg"); + if (_tmp0_ == 0) { + book_save_multi_file (self, "jpeg", file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp1_; + _tmp1_ = g_strcmp0 (type, "png"); + if (_tmp1_ == 0) { + book_save_multi_file (self, "png", file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp2_; + _tmp2_ = g_strcmp0 (type, "tiff"); + if (_tmp2_ == 0) { + book_save_multi_file (self, "tiff", file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp3_; + _tmp3_ = g_strcmp0 (type, "ps"); + if (_tmp3_ == 0) { + book_save_ps (self, file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp4_; + _tmp4_ = g_strcmp0 (type, "pdf"); + if (_tmp4_ == 0) { + book_save_pdf (self, file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } + } + } + } + } +} + + +void book_set_needs_saving (Book* self, gboolean needs_saving) { + gboolean needed_saving; + g_return_if_fail (self != NULL); + needed_saving = self->priv->needs_saving; + self->priv->needs_saving = needs_saving; + if (needed_saving != needs_saving) { + g_signal_emit_by_name (self, "needs-saving-changed"); + } +} + + +gboolean book_get_needs_saving (Book* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->needs_saving; + return result; +} + + +static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__PAGE) (gpointer data1, gpointer arg_1, gpointer data2); + register GMarshalFunc_VOID__PAGE callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 2); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__PAGE) (marshal_data ? marshal_data : cc->callback); + callback (data1, value_get_page (param_values + 1), data2); +} + + +static void value_book_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_book_free_value (GValue* value) { + if (value->data[0].v_pointer) { + book_unref (value->data[0].v_pointer); + } +} + + +static void value_book_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = book_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_book_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_book_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Book* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = book_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_book_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Book** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = book_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecBook* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_BOOK), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_book (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK), NULL); + return value->data[0].v_pointer; +} + + +void value_set_book (GValue* value, gpointer v_object) { + Book* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BOOK)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + book_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + book_unref (old); + } +} -Book * -book_new () -{ - return g_object_new (BOOK_TYPE, NULL); +void value_take_book (GValue* value, gpointer v_object) { + Book* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BOOK)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + book_unref (old); + } } -void -book_clear (Book *book) -{ - GList *iter; - for (iter = book->priv->pages; iter; iter = iter->next) { - Page *page = iter->data; - g_object_unref (page); - } - g_list_free (book->priv->pages); - book->priv->pages = NULL; - g_signal_emit (book, signals[CLEARED], 0); +static void book_class_init (BookClass * klass) { + book_parent_class = g_type_class_peek_parent (klass); + BOOK_CLASS (klass)->finalize = book_finalize; + g_type_class_add_private (klass, sizeof (BookPrivate)); + g_signal_new ("page_added", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE); + g_signal_new ("page_removed", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE); + g_signal_new ("reordered", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("cleared", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("needs_saving_changed", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } -static void -page_changed_cb (Page *page, Book *book) -{ - book_set_needs_saving (book, TRUE); +static void book_instance_init (Book * self) { + self->priv = BOOK_GET_PRIVATE (self); + self->ref_count = 1; } -Page * -book_append_page (Book *book, gint width, gint height, gint dpi, ScanDirection scan_direction) -{ - Page *page; +static void book_finalize (Book* obj) { + Book * self; + self = BOOK (obj); + __g_list_free__page_unref0_0 (self->priv->pages); +} - page = page_new (width, height, dpi, scan_direction); - g_signal_connect (page, "pixels-changed", G_CALLBACK (page_changed_cb), book); - g_signal_connect (page, "crop-changed", G_CALLBACK (page_changed_cb), book); - book->priv->pages = g_list_append (book->priv->pages, page); +GType book_get_type (void) { + static volatile gsize book_type_id__volatile = 0; + if (g_once_init_enter (&book_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_book_init, value_book_free_value, value_book_copy_value, value_book_peek_pointer, "p", value_book_collect_value, "p", value_book_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (BookClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) book_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Book), 0, (GInstanceInitFunc) book_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType book_type_id; + book_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Book", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&book_type_id__volatile, book_type_id); + } + return book_type_id__volatile; +} - g_signal_emit (book, signals[PAGE_ADDED], 0, page); - - book_set_needs_saving (book, TRUE); - return page; +gpointer book_ref (gpointer instance) { + Book* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -void -book_move_page (Book *book, Page *page, gint location) -{ - book->priv->pages = g_list_remove (book->priv->pages, page); - book->priv->pages = g_list_insert (book->priv->pages, page, location); +void book_unref (gpointer instance) { + Book* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + BOOK_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} - g_signal_emit (book, signals[REORDERED], 0, page); - book_set_needs_saving (book, TRUE); +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; } -void -book_delete_page (Book *book, Page *page) -{ - g_signal_handlers_disconnect_by_func (page, page_changed_cb, book); +PDFWriter* pdf_writer_construct (GType object_type, GFileOutputStream* stream) { + PDFWriter* self = NULL; + GFileOutputStream* _tmp0_; + g_return_val_if_fail (stream != NULL, NULL); + self = (PDFWriter*) g_type_create_instance (object_type); + _tmp0_ = _g_object_ref0 (stream); + _g_object_unref0 (self->priv->stream); + self->priv->stream = _tmp0_; + return self; +} - g_signal_emit (book, signals[PAGE_REMOVED], 0, page); - book->priv->pages = g_list_remove (book->priv->pages, page); - g_object_unref (page); +PDFWriter* pdf_writer_new (GFileOutputStream* stream) { + return pdf_writer_construct (TYPE_PDF_WRITER, stream); +} + - book_set_needs_saving (book, TRUE); +void pdf_writer_write (PDFWriter* self, guint8* data, int data_length1) { + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + { + g_output_stream_write_all ((GOutputStream*) self->priv->stream, data, (gsize) data_length1, NULL, NULL, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch0_g_error; + } + } + goto __finally0; + __catch0_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("book.vala:529: Error writing PDF: %s", e->message); + _g_error_free0 (e); + } + __finally0: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + self->offset = self->offset + data_length1; } -gint -book_get_n_pages (Book *book) -{ - return g_list_length (book->priv->pages); +static gchar* string_to_utf8 (const gchar* self, int* result_length1) { + gchar* result = NULL; + gint _tmp0_; + gchar* _tmp1_ = NULL; + gchar* _result_; + gint _result__length1; + gint __result__size_; + gint _tmp2_; + gchar* _tmp3_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = strlen (self); + _tmp1_ = g_new0 (gchar, _tmp0_ + 1); + _result_ = _tmp1_; + _result__length1 = _tmp0_ + 1; + __result__size_ = _result__length1; + _result__length1--; + _tmp2_ = strlen (self); + memcpy (_result_, self, (gsize) _tmp2_); + _tmp3_ = _result_; + if (result_length1) { + *result_length1 = _result__length1; + } + result = _tmp3_; + return result; } -Page * -book_get_page (Book *book, gint page_number) -{ - if (page_number < 0) - page_number = g_list_length (book->priv->pages) + page_number; - return g_list_nth_data (book->priv->pages, page_number); +void pdf_writer_write_string (PDFWriter* self, const gchar* text) { + gint _tmp0_; + gchar* _tmp1_ = NULL; + guint8* _tmp2_; + gint _tmp2__length1; + g_return_if_fail (self != NULL); + g_return_if_fail (text != NULL); + _tmp1_ = string_to_utf8 (text, &_tmp0_); + _tmp2_ = (guint8*) _tmp1_; + _tmp2__length1 = _tmp0_; + pdf_writer_write (self, _tmp2_, _tmp0_); + _tmp2_ = (g_free (_tmp2_), NULL); } -gint -book_get_page_index (Book *book, Page *page) -{ - return g_list_index (book->priv->pages, page); +guint pdf_writer_start_object (PDFWriter* self) { + guint result = 0U; + guint _tmp0_; + g_return_val_if_fail (self != NULL, 0U); + self->object_offsets = g_list_append (self->object_offsets, GUINT_TO_POINTER ((guint) self->offset)); + _tmp0_ = g_list_length (self->object_offsets); + result = _tmp0_; + return result; } -static GFile * -make_indexed_file (const gchar *uri, gint i) -{ - gchar *basename, *suffix, *indexed_uri; - GFile *file; +static void value_pdf_writer_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + - if (i == 0) - return g_file_new_for_uri (uri); +static void value_pdf_writer_free_value (GValue* value) { + if (value->data[0].v_pointer) { + pdf_writer_unref (value->data[0].v_pointer); + } +} - basename = g_path_get_basename (uri); - suffix = g_strrstr (basename, "."); - if (suffix) - indexed_uri = g_strdup_printf ("%.*s-%d%s", (int) (strlen (uri) - strlen (suffix)), uri, i, suffix); - else - indexed_uri = g_strdup_printf ("%s-%d", uri, i); - g_free (basename); +static void value_pdf_writer_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = pdf_writer_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} - file = g_file_new_for_uri (indexed_uri); - g_free (indexed_uri); - return file; +static gpointer value_pdf_writer_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; } -static gboolean -book_save_multi_file (Book *book, const gchar *type, GFile *file, GError **error) -{ - GList *iter; - gboolean result = TRUE; - gint i; - gchar *uri; +static gchar* value_pdf_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + PDFWriter* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = pdf_writer_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} - uri = g_file_get_uri (file); - for (iter = book->priv->pages, i = 0; iter && result; iter = iter->next, i++) { - Page *page = iter->data; - GFile *file; - file = make_indexed_file (uri, i); - result = page_save (page, type, file, error); - g_object_unref (file); - } - g_free (uri); - - return result; +static gchar* value_pdf_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + PDFWriter** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = pdf_writer_ref (value->data[0].v_pointer); + } + return NULL; } -static void -save_ps_pdf_surface (cairo_surface_t *surface, GdkPixbuf *image, gdouble dpi) -{ - cairo_t *context; - - context = cairo_create (surface); +GParamSpec* param_spec_pdf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPDFWriter* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PDF_WRITER), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} - cairo_scale (context, 72.0 / dpi, 72.0 / dpi); - gdk_cairo_set_source_pixbuf (context, image, 0, 0); - cairo_pattern_set_filter (cairo_get_source (context), CAIRO_FILTER_BEST); - cairo_paint (context); - cairo_destroy (context); +gpointer value_get_pdf_writer (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER), NULL); + return value->data[0].v_pointer; } -static cairo_status_t -write_cairo_data (GFileOutputStream *stream, unsigned char *data, unsigned int length) -{ - gboolean result; - GError *error = NULL; +void value_set_pdf_writer (GValue* value, gpointer v_object) { + PDFWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PDF_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + pdf_writer_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + pdf_writer_unref (old); + } +} - result = g_output_stream_write_all (G_OUTPUT_STREAM (stream), data, length, NULL, NULL, &error); - - if (error) { - g_warning ("Error writing data: %s", error->message); - g_error_free (error); - } - return result ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR; +void value_take_pdf_writer (GValue* value, gpointer v_object) { + PDFWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PDF_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + pdf_writer_unref (old); + } } -static gboolean -book_save_ps (Book *book, GFile *file, GError **error) -{ - GFileOutputStream *stream; - GList *iter; - cairo_surface_t *surface; +static void pdf_writer_class_init (PDFWriterClass * klass) { + pdf_writer_parent_class = g_type_class_peek_parent (klass); + PDF_WRITER_CLASS (klass)->finalize = pdf_writer_finalize; + g_type_class_add_private (klass, sizeof (PDFWriterPrivate)); +} - stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); - if (!stream) - return FALSE; - surface = cairo_ps_surface_create_for_stream ((cairo_write_func_t) write_cairo_data, - stream, 0, 0); +static void pdf_writer_instance_init (PDFWriter * self) { + self->priv = PDF_WRITER_GET_PRIVATE (self); + self->offset = (gsize) 0; + self->ref_count = 1; +} - for (iter = book->priv->pages; iter; iter = iter->next) { - Page *page = iter->data; - double width, height; - GdkPixbuf *image; - image = page_get_image (page, TRUE); +static void pdf_writer_finalize (PDFWriter* obj) { + PDFWriter * self; + self = PDF_WRITER (obj); + _g_list_free0 (self->object_offsets); + _g_object_unref0 (self->priv->stream); +} - width = gdk_pixbuf_get_width (image) * 72.0 / page_get_dpi (page); - height = gdk_pixbuf_get_height (image) * 72.0 / page_get_dpi (page); - cairo_ps_surface_set_size (surface, width, height); - save_ps_pdf_surface (surface, image, page_get_dpi (page)); - cairo_surface_show_page (surface); - - g_object_unref (image); - } - cairo_surface_destroy (surface); +GType pdf_writer_get_type (void) { + static volatile gsize pdf_writer_type_id__volatile = 0; + if (g_once_init_enter (&pdf_writer_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_pdf_writer_init, value_pdf_writer_free_value, value_pdf_writer_copy_value, value_pdf_writer_peek_pointer, "p", value_pdf_writer_collect_value, "p", value_pdf_writer_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PDFWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pdf_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PDFWriter), 0, (GInstanceInitFunc) pdf_writer_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType pdf_writer_type_id; + pdf_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PDFWriter", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&pdf_writer_type_id__volatile, pdf_writer_type_id); + } + return pdf_writer_type_id__volatile; +} - g_object_unref (stream); - return TRUE; +gpointer pdf_writer_ref (gpointer instance) { + PDFWriter* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -typedef struct -{ - int offset; - int n_objects; - GList *object_offsets; - GFileOutputStream *stream; -} PDFWriter; +void pdf_writer_unref (gpointer instance) { + PDFWriter* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PDF_WRITER_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} -static PDFWriter * -pdf_writer_new (GFileOutputStream *stream) -{ - PDFWriter *writer; - writer = g_malloc0 (sizeof (PDFWriter)); - writer->stream = g_object_ref (stream); - return writer; +static cairo_status_t _ps_writer_write_cairo_data_cairo_write_func_t (gpointer self, guchar* data, int data_length1) { + cairo_status_t result; + result = ps_writer_write_cairo_data (self, data, data_length1); + return result; } -static void -pdf_writer_free (PDFWriter *writer) -{ - g_object_unref (writer->stream); - g_list_free (writer->object_offsets); - g_free (writer); +PsWriter* ps_writer_construct (GType object_type, GFileOutputStream* stream) { + PsWriter* self = NULL; + GFileOutputStream* _tmp0_; + cairo_surface_t* _tmp1_ = NULL; + g_return_val_if_fail (stream != NULL, NULL); + self = (PsWriter*) g_type_create_instance (object_type); + _tmp0_ = _g_object_ref0 (stream); + _g_object_unref0 (self->stream); + self->stream = _tmp0_; + _tmp1_ = cairo_ps_surface_create_for_stream (_ps_writer_write_cairo_data_cairo_write_func_t, self, (gdouble) 0, (gdouble) 0); + _cairo_surface_destroy0 (self->surface); + self->surface = _tmp1_; + return self; } -static void -pdf_write (PDFWriter *writer, const unsigned char *data, size_t length) -{ - g_output_stream_write_all (G_OUTPUT_STREAM (writer->stream), data, length, NULL, NULL, NULL); - writer->offset += length; +PsWriter* ps_writer_new (GFileOutputStream* stream) { + return ps_writer_construct (TYPE_PS_WRITER, stream); } -static void -pdf_printf (PDFWriter *writer, const char *format, ...) -{ - va_list args; - gchar *string; +static cairo_status_t ps_writer_write_cairo_data (PsWriter* self, guint8* data, int data_length1) { + cairo_status_t result = 0; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, 0); + { + g_output_stream_write_all ((GOutputStream*) self->stream, data, (gsize) data_length1, NULL, NULL, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch1_g_error; + } + } + goto __finally1; + __catch1_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("book.vala:565: Error writing data: %s", e->message); + result = CAIRO_STATUS_WRITE_ERROR; + _g_error_free0 (e); + return result; + } + __finally1: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return 0; + } + result = CAIRO_STATUS_SUCCESS; + return result; +} - va_start (args, format); - string = g_strdup_vprintf (format, args); - va_end (args); - pdf_write (writer, (unsigned char *)string, strlen (string)); - g_free (string); +static void value_ps_writer_init (GValue* value) { + value->data[0].v_pointer = NULL; } -static int -pdf_start_object (PDFWriter *writer) -{ - writer->n_objects++; - writer->object_offsets = g_list_append (writer->object_offsets, GINT_TO_POINTER (writer->offset)); - return writer->n_objects; +static void value_ps_writer_free_value (GValue* value) { + if (value->data[0].v_pointer) { + ps_writer_unref (value->data[0].v_pointer); + } } -static guchar * -compress_zlib (guchar *data, size_t length, size_t *n_written) -{ - z_stream stream; - guchar *out_data; +static void value_ps_writer_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = ps_writer_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} - out_data = g_malloc (sizeof (guchar) * length); - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - if (deflateInit (&stream, Z_BEST_COMPRESSION) != Z_OK) - return NULL; +static gpointer value_ps_writer_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} - stream.next_in = data; - stream.avail_in = length; - stream.next_out = out_data; - stream.avail_out = length; - while (stream.avail_in > 0) { - if (deflate (&stream, Z_FINISH) == Z_STREAM_ERROR) - break; - } - deflateEnd (&stream); +static gchar* value_ps_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + PsWriter* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = ps_writer_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + - if (stream.avail_in > 0) { - g_free (out_data); - return NULL; - } +static gchar* value_ps_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + PsWriter** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = ps_writer_ref (value->data[0].v_pointer); + } + return NULL; +} - *n_written = length - stream.avail_out; - return out_data; +GParamSpec* param_spec_ps_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPsWriter* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PS_WRITER), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); } - - -static void jpeg_init_cb (struct jpeg_compress_struct *info) {} -static boolean jpeg_empty_cb (struct jpeg_compress_struct *info) { return TRUE; } -static void jpeg_term_cb (struct jpeg_compress_struct *info) {} - -static guchar * -compress_jpeg (GdkPixbuf *image, size_t *n_written) -{ - struct jpeg_compress_struct info; - struct jpeg_error_mgr jerr; - struct jpeg_destination_mgr dest_mgr; - int r; - guchar *pixels; - guchar *data; - size_t max_length; - - info.err = jpeg_std_error (&jerr); - jpeg_create_compress (&info); - - pixels = gdk_pixbuf_get_pixels (image); - info.image_width = gdk_pixbuf_get_width (image); - info.image_height = gdk_pixbuf_get_height (image); - info.input_components = 3; - info.in_color_space = JCS_RGB; /* TODO: JCS_GRAYSCALE? */ - jpeg_set_defaults (&info); - - max_length = info.image_width * info.image_height * info.input_components; - data = g_malloc (sizeof (guchar) * max_length); - dest_mgr.next_output_byte = data; - dest_mgr.free_in_buffer = max_length; - dest_mgr.init_destination = jpeg_init_cb; - dest_mgr.empty_output_buffer = jpeg_empty_cb; - dest_mgr.term_destination = jpeg_term_cb; - info.dest = &dest_mgr; - - jpeg_start_compress (&info, TRUE); - for (r = 0; r < info.image_height; r++) { - JSAMPROW row[1]; - row[0] = pixels + r * gdk_pixbuf_get_rowstride (image); - jpeg_write_scanlines (&info, row, 1); - } - jpeg_finish_compress (&info); - *n_written = max_length - dest_mgr.free_in_buffer; - - jpeg_destroy_compress (&info); - - return data; -} - - -static gboolean -book_save_pdf (Book *book, GFile *file, GError **error) -{ - GFileOutputStream *stream; - PDFWriter *writer; - int catalog_number, pages_number, info_number; - int xref_offset; - int i; - - stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); - if (!stream) - return FALSE; - - writer = pdf_writer_new (stream); - g_object_unref (stream); - - /* Header */ - pdf_printf (writer, "%%PDF-1.3\n"); - - /* Comment with binary as recommended so file is treated as binary */ - pdf_printf (writer, "%%\xe2\xe3\xcf\xd3\n"); - - /* Catalog */ - catalog_number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", catalog_number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Catalog\n"); - //FIXMEpdf_printf (writer, "/Metadata %d 0 R\n", catalog_number + 1); - pdf_printf (writer, "/Pages %d 0 R\n", catalog_number + 1); //+2 - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - /* Metadata */ - /* FIXME pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Metadata\n"); - pdf_printf (writer, "/Subtype /XML\n"); - pdf_printf (writer, "/Length %d\n", ...); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "stream\n"); - // ... - pdf_printf (writer, "\n"); - pdf_printf (writer, "endstream\n"); - pdf_printf (writer, "endobj\n");*/ - - /* Pages */ - pdf_printf (writer, "\n"); - pages_number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", pages_number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Pages\n"); - pdf_printf (writer, "/Kids ["); - for (i = 0; i < book_get_n_pages (book); i++) { - pdf_printf (writer, " %d 0 R", pages_number + 1 + (i*3)); - } - pdf_printf (writer, " ]\n"); - pdf_printf (writer, "/Count %d\n", book_get_n_pages (book)); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - for (i = 0; i < book_get_n_pages (book); i++) { - int number, width, height, depth; - size_t data_length, compressed_length; - Page *page; - GdkPixbuf *image; - guchar *pixels, *data, *compressed_data; - gchar *command, width_buffer[G_ASCII_DTOSTR_BUF_SIZE], height_buffer[G_ASCII_DTOSTR_BUF_SIZE]; - const gchar *color_space, *filter = NULL; - float page_width, page_height; - - page = book_get_page (book, i); - image = page_get_image (page, TRUE); - width = gdk_pixbuf_get_width (image); - height = gdk_pixbuf_get_height (image); - pixels = gdk_pixbuf_get_pixels (image); - page_width = width * 72. / page_get_dpi (page); - page_height = height * 72. / page_get_dpi (page); - - if (page_is_color (page)) { - int row; - - depth = 8; - color_space = "DeviceRGB"; - data_length = height * width * 3 + 1; - data = g_malloc (sizeof (guchar) * data_length); - for (row = 0; row < height; row++) { - int x; - guchar *in_line, *out_line; - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - out_line = data + row * width * 3; - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - guchar *out_p = out_line + x*3; - - out_p[0] = in_p[0]; - out_p[1] = in_p[1]; - out_p[2] = in_p[2]; - } - } - } - else if (page_get_depth (page) == 2) { - int row, shift_count = 6; - guchar *write_ptr; - - depth = 2; - color_space = "DeviceGray"; - data_length = height * ((width * 2 + 7) / 8); - data = g_malloc (sizeof (guchar) * data_length); - write_ptr = data; - write_ptr[0] = 0; - for (row = 0; row < height; row++) { - int x; - guchar *in_line; - - /* Pad to the next line */ - if (shift_count != 6) { - write_ptr++; - write_ptr[0] = 0; - shift_count = 6; - } - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - if (in_p[0] >= 192) - write_ptr[0] |= 3 << shift_count; - else if (in_p[0] >= 128) - write_ptr[0] |= 2 << shift_count; - else if (in_p[0] >= 64) - write_ptr[0] |= 1 << shift_count; - if (shift_count == 0) { - write_ptr++; - write_ptr[0] = 0; - shift_count = 6; - } - else - shift_count -= 2; - } - } - } - else if (page_get_depth (page) == 1) { - int row, mask = 0x80; - guchar *write_ptr; - - depth = 1; - color_space = "DeviceGray"; - data_length = height * ((width + 7) / 8); - data = g_malloc (sizeof (guchar) * data_length); - write_ptr = data; - write_ptr[0] = 0; - for (row = 0; row < height; row++) { - int x; - guchar *in_line; - - /* Pad to the next line */ - if (mask != 0x80) { - write_ptr++; - write_ptr[0] = 0; - mask = 0x80; - } - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - if (in_p[0] != 0) - write_ptr[0] |= mask; - mask >>= 1; - if (mask == 0) { - write_ptr++; - write_ptr[0] = 0; - mask = 0x80; - } - } - } - } - else { - int row; - - depth = 8; - color_space = "DeviceGray"; - data_length = height * width + 1; - data = g_malloc (sizeof (guchar) * data_length); - for (row = 0; row < height; row++) { - int x; - guchar *in_line, *out_line; - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - out_line = data + row * width; - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - guchar *out_p = out_line + x; - - out_p[0] = in_p[0]; - } - } - } - - /* Compress data */ - compressed_data = compress_zlib (data, data_length, &compressed_length); - if (compressed_data) { - /* Try if JPEG compression is better */ - if (depth > 1) { - guchar *jpeg_data; - size_t jpeg_length; - - jpeg_data = compress_jpeg (image, &jpeg_length); - if (jpeg_length < compressed_length) { - filter = "DCTDecode"; - g_free (data); - g_free (compressed_data); - data = jpeg_data; - data_length = jpeg_length; - } - } - - if (!filter) { - filter = "FlateDecode"; - g_free (data); - data = compressed_data; - data_length = compressed_length; - } - } - - /* Page */ - pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Page\n"); - pdf_printf (writer, "/Parent %d 0 R\n", pages_number); - pdf_printf (writer, "/Resources << /XObject << /Im%d %d 0 R >> >>\n", i, number+1); - pdf_printf (writer, "/MediaBox [ 0 0 %s %s ]\n", - g_ascii_formatd (width_buffer, sizeof (width_buffer), "%.2f", page_width), - g_ascii_formatd (height_buffer, sizeof (height_buffer), "%.2f", page_height)); - pdf_printf (writer, "/Contents %d 0 R\n", number+2); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - /* Page image */ - pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /XObject\n"); - pdf_printf (writer, "/Subtype /Image\n"); - pdf_printf (writer, "/Width %d\n", width); - pdf_printf (writer, "/Height %d\n", height); - pdf_printf (writer, "/ColorSpace /%s\n", color_space); - pdf_printf (writer, "/BitsPerComponent %d\n", depth); - pdf_printf (writer, "/Length %d\n", data_length); - if (filter) - pdf_printf (writer, "/Filter /%s\n", filter); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "stream\n"); - pdf_write (writer, data, data_length); - g_free (data); - pdf_printf (writer, "\n"); - pdf_printf (writer, "endstream\n"); - pdf_printf (writer, "endobj\n"); - - /* Page contents */ - command = g_strdup_printf ("q\n" - "%s 0 0 %s 0 0 cm\n" - "/Im%d Do\n" - "Q", - g_ascii_formatd (width_buffer, sizeof (width_buffer), "%f", page_width), - g_ascii_formatd (height_buffer, sizeof (height_buffer), "%f", page_height), - i); - pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Length %d\n", strlen (command) + 1); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "stream\n"); - pdf_write (writer, (unsigned char *)command, strlen (command)); - pdf_printf (writer, "\n"); - pdf_printf (writer, "endstream\n"); - pdf_printf (writer, "endobj\n"); - g_free (command); - - g_object_unref (image); - } - - /* Info */ - pdf_printf (writer, "\n"); - info_number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", info_number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Creator (Simple Scan " VERSION ")\n"); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - /* Cross-reference table */ - xref_offset = writer->offset; - pdf_printf (writer, "xref\n"); - pdf_printf (writer, "1 %d\n", writer->n_objects); - GList *link; - for (link = writer->object_offsets; link != NULL; link = link->next) { - int offset = GPOINTER_TO_INT (link->data); - pdf_printf (writer, "%010d 0000 n\n", offset); - } - - /* Trailer */ - pdf_printf (writer, "trailer\n"); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Size %d\n", writer->n_objects); - pdf_printf (writer, "/Info %d 0 R\n", info_number); - pdf_printf (writer, "/Root %d 0 R\n", catalog_number); - //FIXME: pdf_printf (writer, "/ID [<...> <...>]\n"); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "startxref\n"); - pdf_printf (writer, "%d\n", xref_offset); - pdf_printf (writer, "%%%%EOF\n"); - - pdf_writer_free (writer); - - return TRUE; -} - - -gboolean -book_save (Book *book, const gchar *type, GFile *file, GError **error) -{ - gboolean result = FALSE; - - if (strcmp (type, "jpeg") == 0) - result = book_save_multi_file (book, "jpeg", file, error); - else if (strcmp (type, "png") == 0) - result = book_save_multi_file (book, "png", file, error); - else if (strcmp (type, "tiff") == 0) - result = book_save_multi_file (book, "tiff", file, error); - else if (strcmp (type, "ps") == 0) - result = book_save_ps (book, file, error); - else if (strcmp (type, "pdf") == 0) - result = book_save_pdf (book, file, error); - - return result; -} - - -void -book_set_needs_saving (Book *book, gboolean needs_saving) -{ - gboolean needed_saving = book->priv->needs_saving; - book->priv->needs_saving = needs_saving; - if (needed_saving != needs_saving) - g_object_notify (G_OBJECT (book), "needs-saving"); -} - - -gboolean -book_get_needs_saving (Book *book) -{ - return book->priv->needs_saving; -} - - -static void -book_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - Book *self; - - self = BOOK (object); - - switch (prop_id) { - case PROP_NEEDS_SAVING: - book_set_needs_saving (self, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -book_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - Book *self; - - self = BOOK (object); - - switch (prop_id) { - case PROP_NEEDS_SAVING: - g_value_set_boolean (value, book_get_needs_saving (self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -book_finalize (GObject *object) -{ - Book *book = BOOK (object); - book_clear (book); - G_OBJECT_CLASS (book_parent_class)->finalize (object); -} - - -static void -book_class_init (BookClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = book_get_property; - object_class->set_property = book_set_property; - object_class->finalize = book_finalize; - - g_object_class_install_property (object_class, - PROP_NEEDS_SAVING, - g_param_spec_boolean ("needs-saving", - "needs-saving", - "TRUE if this book needs saving", - FALSE, - G_PARAM_READWRITE)); - - signals[PAGE_ADDED] = - g_signal_new ("page-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, page_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, page_get_type ()); - signals[PAGE_REMOVED] = - g_signal_new ("page-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, page_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, page_get_type ()); - signals[REORDERED] = - g_signal_new ("reordered", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, reordered), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[CLEARED] = - g_signal_new ("cleared", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, cleared), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (BookPrivate)); -} - - -static void -book_init (Book *book) -{ - book->priv = G_TYPE_INSTANCE_GET_PRIVATE (book, BOOK_TYPE, BookPrivate); + + +gpointer value_get_ps_writer (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER), NULL); + return value->data[0].v_pointer; } + + +void value_set_ps_writer (GValue* value, gpointer v_object) { + PsWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PS_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + ps_writer_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + ps_writer_unref (old); + } +} + + +void value_take_ps_writer (GValue* value, gpointer v_object) { + PsWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PS_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + ps_writer_unref (old); + } +} + + +static void ps_writer_class_init (PsWriterClass * klass) { + ps_writer_parent_class = g_type_class_peek_parent (klass); + PS_WRITER_CLASS (klass)->finalize = ps_writer_finalize; +} + + +static void ps_writer_instance_init (PsWriter * self) { + self->ref_count = 1; +} + + +static void ps_writer_finalize (PsWriter* obj) { + PsWriter * self; + self = PS_WRITER (obj); + _cairo_surface_destroy0 (self->surface); + _g_object_unref0 (self->stream); +} + + +GType ps_writer_get_type (void) { + static volatile gsize ps_writer_type_id__volatile = 0; + if (g_once_init_enter (&ps_writer_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_ps_writer_init, value_ps_writer_free_value, value_ps_writer_copy_value, value_ps_writer_peek_pointer, "p", value_ps_writer_collect_value, "p", value_ps_writer_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PsWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ps_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PsWriter), 0, (GInstanceInitFunc) ps_writer_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType ps_writer_type_id; + ps_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PsWriter", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&ps_writer_type_id__volatile, ps_writer_type_id); + } + return ps_writer_type_id__volatile; +} + + +gpointer ps_writer_ref (gpointer instance) { + PsWriter* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void ps_writer_unref (gpointer instance) { + PsWriter* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PS_WRITER_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + + diff --git a/src/book.h b/src/book.h deleted file mode 100644 index cf82978..0000000 --- a/src/book.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2009 Canonical Ltd. - * Author: Robert Ancell <robert.ancell@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. See http://www.gnu.org/copyleft/gpl.html the full text of the - * license. - */ - -#ifndef _BOOK_H_ -#define _BOOK_H_ - -#include <glib-object.h> -#include <gio/gio.h> -#include <cairo.h> -#include "page.h" - -G_BEGIN_DECLS - -#define BOOK_TYPE (book_get_type ()) -#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BOOK_TYPE, Book)) - - -typedef struct BookPrivate BookPrivate; - -typedef struct -{ - GObject parent_instance; - BookPrivate *priv; -} Book; - -typedef struct -{ - GObjectClass parent_class; - - void (*page_added) (Book *book, Page *page); - void (*page_removed) (Book *book, Page *page); - void (*reordered) (Book *book); - void (*cleared) (Book *book); -} BookClass; - - -GType book_get_type (void); - -Book *book_new (void); - -void book_clear (Book *book); - -Page *book_append_page (Book *book, gint width, gint height, gint dpi, ScanDirection orientation); - -void book_move_page (Book *book, Page *page, gint location); - -void book_delete_page (Book *book, Page *page); - -gint book_get_n_pages (Book *book); - -Page *book_get_page (Book *book, gint page_number); - -gint book_get_page_index (Book *book, Page *page); - -gboolean book_save (Book *book, const gchar *type, GFile *file, GError **error); - -void book_set_needs_saving (Book *book, gboolean needs_saving); - -gboolean book_get_needs_saving (Book *book); - -#endif /* _BOOK_H_ */ diff --git a/src/book.vala b/src/book.vala new file mode 100644 index 0000000..1aed281 --- /dev/null +++ b/src/book.vala @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public class Book +{ + private List<Page> pages; + + private bool needs_saving; + + public signal void page_added (Page page); + public signal void page_removed (Page page); + public signal void reordered (); + public signal void cleared (); + public signal void needs_saving_changed (); + + public Book () + { + } + + public void clear () + { + pages = null; + cleared (); + } + + private void page_changed_cb (Page page) + { + set_needs_saving (true); + } + + public Page append_page (int width, int height, int dpi, ScanDirection scan_direction) + { + var page = new Page (width, height, dpi, scan_direction); + page.pixels_changed.connect (page_changed_cb); + page.crop_changed.connect (page_changed_cb); + + pages.append (page); + page_added (page); + set_needs_saving (true); + + return page; + } + + public void move_page (Page page, uint location) + { + pages.remove (page); + pages.insert (page, (int) location); + reordered (); + set_needs_saving (true); + } + + public void delete_page (Page page) + { + page.pixels_changed.disconnect (page_changed_cb); + page.crop_changed.disconnect (page_changed_cb); + page_removed (page); + pages.remove (page); + set_needs_saving (true); + } + + public uint get_n_pages () + { + return pages.length (); + } + + public Page get_page (int page_number) + { + if (page_number < 0) + page_number = (int) pages.length () + page_number; + return pages.nth_data (page_number); + } + + public uint get_page_index (Page page) + { + return pages.index (page); + } + + private File make_indexed_file (string uri, int i) + { + if (i == 0) + return File.new_for_uri (uri); + + /* Insert index before extension */ + var basename = Path.get_basename (uri); + string prefix = uri, suffix = ""; + var extension_index = basename.last_index_of_char ('.'); + if (extension_index >= 0) + { + suffix = basename.slice (extension_index, basename.length); + prefix = uri.slice (0, uri.length - suffix.length); + } + + return File.new_for_uri ("%s-%d%s".printf (prefix, i, suffix)); + } + + private void save_multi_file (string type, File file) throws Error + { + int i = 0; + foreach (var page in pages) + { + page.save (type, make_indexed_file (file.get_uri (), i)); + i++; + } + } + + private void save_ps_pdf_surface (Cairo.Surface surface, Gdk.Pixbuf image, double dpi) + { + var context = new Cairo.Context (surface); + context.scale (72.0 / dpi, 72.0 / dpi); + Gdk.cairo_set_source_pixbuf (context, image, 0, 0); + context.get_source ().set_filter (Cairo.Filter.BEST); + context.paint (); + } + + private void save_ps (File file) throws Error + { + var stream = file.replace (null, false, FileCreateFlags.NONE, null); + var writer = new PsWriter (stream); + var surface = writer.surface; + + foreach (var page in pages) + { + var image = page.get_image (true); + var width = image.get_width () * 72.0 / page.get_dpi (); + var height = image.get_height () * 72.0 / page.get_dpi (); + surface.set_size (width, height); + save_ps_pdf_surface (surface, image, page.get_dpi ()); + surface.show_page (); + } + } + + private uint8[]? compress_zlib (uint8[] data) + { + var stream = ZLib.DeflateStream (ZLib.Level.BEST_COMPRESSION); + var out_data = new uint8[data.length]; + + stream.next_in = data; + stream.next_out = out_data; + while (stream.avail_in > 0) + { + if (stream.deflate (ZLib.Flush.FINISH) == ZLib.Status.STREAM_ERROR) + break; + } + + if (stream.avail_in > 0) + return null; + + var n_written = data.length - stream.avail_out; + out_data.resize ((int) n_written); + + return out_data; + } + + private static void jpeg_init_cb (JPEG.Compress info) {} + private static bool jpeg_empty_cb (JPEG.Compress info) { return true; } + private static void jpeg_term_cb (JPEG.Compress info) {} + + private uint8[] compress_jpeg (Gdk.Pixbuf image, out size_t n_written) + { + var info = JPEG.Compress (); + var jerr = JPEG.ErrorManager (); + var dest_mgr = JPEG.DestinationManager (); + + info.err = jerr.std_error (); + info.create_compress (); + + info.image_width = image.get_width (); + info.image_height = image.get_height (); + info.input_components = 3; + info.in_color_space = JPEG.ColorSpace.RGB; /* TODO: JCS_GRAYSCALE? */ + info.set_defaults (); + + var max_length = info.image_width * info.image_height * info.input_components; + var data = new uint8[max_length]; + dest_mgr.next_output_byte = data; + dest_mgr.free_in_buffer = max_length; + dest_mgr.init_destination = jpeg_init_cb; + dest_mgr.empty_output_buffer = jpeg_empty_cb; + dest_mgr.term_destination = jpeg_term_cb; + info.dest = &dest_mgr; + + info.start_compress (true); + unowned uint8[] pixels = image.get_pixels (); + for (var r = 0; r < info.image_height; r++) + { + uint8* row[1]; + row[0] = (uint8*) pixels + r * image.get_rowstride (); + info.write_scanlines (row, 1); + } + info.finish_compress (); + n_written = max_length - dest_mgr.free_in_buffer; + + return data; + } + + private void save_pdf (File file) throws Error + { + var stream = file.replace (null, false, FileCreateFlags.NONE, null); + var writer = new PDFWriter (stream); + + /* Header */ + writer.write_string ("%%PDF-1.3\n"); + + /* Comment with binary as recommended so file is treated as binary */ + writer.write_string ("%%\xe2\xe3\xcf\xd3\n"); + + /* Catalog */ + var catalog_number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (catalog_number)); + writer.write_string ("<<\n"); + writer.write_string ("/Type /Catalog\n"); + //FIXMEwriter.write_string ("/Metadata %u 0 R\n".printf (catalog_number + 1)); + writer.write_string ("/Pages %u 0 R\n".printf (catalog_number + 1)); //+2 + writer.write_string (">>\n"); + writer.write_string ("endobj\n"); + + /* Metadata */ + /* FIXME writer.write_string ("\n"); + number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (number)); + writer.write_string ("<<\n"); + writer.write_string ("/Type /Metadata\n"); + writer.write_string ("/Subtype /XML\n"); + writer.write_string ("/Length %u\n".printf (...)); + writer.write_string (">>\n"); + writer.write_string ("stream\n"); + // ... + writer.write_string ("\n"); + writer.write_string ("endstream\n"); + writer.write_string ("endobj\n");*/ + + /* Pages */ + writer.write_string ("\n"); + var pages_number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (pages_number)); + writer.write_string ("<<\n"); + writer.write_string ("/Type /Pages\n"); + writer.write_string ("/Kids ["); + for (var i = 0; i < get_n_pages (); i++) + writer.write_string (" %u 0 R".printf (pages_number + 1 + (i*3))); + writer.write_string (" ]\n"); + writer.write_string ("/Count %u\n".printf (get_n_pages ())); + writer.write_string (">>\n"); + writer.write_string ("endobj\n"); + + for (var i = 0; i < get_n_pages (); i++) + { + var page = get_page (i); + var image = page.get_image (true); + var width = image.get_width (); + var height = image.get_height (); + unowned uint8[] pixels = image.get_pixels (); + var page_width = width * 72.0 / page.get_dpi (); + var page_height = height * 72.0 / page.get_dpi (); + + int depth = 8; + string color_space = "DeviceRGB"; + string? filter = null; + char[] width_buffer = new char[double.DTOSTR_BUF_SIZE]; + char[] height_buffer = new char[double.DTOSTR_BUF_SIZE]; + uint8[] data; + if (page.is_color ()) + { + depth = 8; + color_space = "DeviceRGB"; + var data_length = height * width * 3 + 1; + data = new uint8[data_length]; + for (var row = 0; row < height; row++) + { + var in_offset = row * image.get_rowstride (); + var out_offset = row * width * 3; + for (var x = 0; x < width; x++) + { + var in_o = in_offset + x*3; + var out_o = out_offset + x*3; + + data[out_o] = pixels[in_o]; + data[out_o+1] = pixels[in_o+1]; + data[out_o+2] = pixels[in_o+2]; + } + } + } + else if (page.get_depth () == 2) + { + int shift_count = 6; + depth = 2; + color_space = "DeviceGray"; + var data_length = height * ((width * 2 + 7) / 8); + data = new uint8[data_length]; + var offset = 0; + data[offset] = 0; + for (var row = 0; row < height; row++) + { + /* Pad to the next line */ + if (shift_count != 6) + { + offset++; + data[offset] = 0; + shift_count = 6; + } + + var in_offset = row * image.get_rowstride (); + for (var x = 0; x < width; x++) + { + var p = pixels[in_offset + x*3]; + if (p >= 192) + data[offset] |= 3 << shift_count; + else if (p >= 128) + data[offset] |= 2 << shift_count; + else if (p >= 64) + data[offset] |= 1 << shift_count; + if (shift_count == 0) + { + offset++; + data[offset] = 0; + shift_count = 6; + } + else + shift_count -= 2; + } + } + } + else if (page.get_depth () == 1) + { + int mask = 0x80; + + depth = 1; + color_space = "DeviceGray"; + var data_length = height * ((width + 7) / 8); + data = new uint8[data_length]; + var offset = 0; + data[offset] = 0; + for (var row = 0; row < height; row++) + { + /* Pad to the next line */ + if (mask != 0x80) + { + offset++; + data[offset] = 0; + mask = 0x80; + } + + var in_offset = row * image.get_rowstride (); + for (var x = 0; x < width; x++) + { + if (pixels[in_offset+x*3] != 0) + data[offset] |= (uint8) mask; + mask >>= 1; + if (mask == 0) + { + offset++; + data[offset] = 0; + mask = 0x80; + } + } + } + } + else + { + depth = 8; + color_space = "DeviceGray"; + var data_length = height * width + 1; + data = new uint8 [data_length]; + for (var row = 0; row < height; row++) + { + var in_offset = row * image.get_rowstride (); + var out_offset = row * width; + for (var x = 0; x < width; x++) + data[out_offset+x] = pixels[in_offset+x*3]; + } + } + + /* Compress data */ + var compressed_data = compress_zlib (data); + if (compressed_data != null) + { + /* Try if JPEG compression is better */ + if (depth > 1) + { + size_t jpeg_length; + var jpeg_data = compress_jpeg (image, out jpeg_length); + if (jpeg_length < compressed_data.length) + { + filter = "DCTDecode"; + data = jpeg_data; + } + } + + if (filter == null) + { + filter = "FlateDecode"; + data = compressed_data; + } + } + + /* Page */ + writer.write_string ("\n"); + var number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (number)); + writer.write_string ("<<\n"); + writer.write_string ("/Type /Page\n"); + writer.write_string ("/Parent %u 0 R\n".printf (pages_number)); + writer.write_string ("/Resources << /XObject << /Im%d %u 0 R >> >>\n".printf (i, number+1)); + writer.write_string ("/MediaBox [ 0 0 %s %s ]\n".printf (page_width.format (width_buffer, "%.2f"), page_height.format (height_buffer, "%.2f"))); + writer.write_string ("/Contents %u 0 R\n".printf (number+2)); + writer.write_string (">>\n"); + writer.write_string ("endobj\n"); + + /* Page image */ + writer.write_string ("\n"); + number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (number)); + writer.write_string ("<<\n"); + writer.write_string ("/Type /XObject\n"); + writer.write_string ("/Subtype /Image\n"); + writer.write_string ("/Width %d\n".printf (width)); + writer.write_string ("/Height %d\n".printf (height)); + writer.write_string ("/ColorSpace /%s\n".printf (color_space)); + writer.write_string ("/BitsPerComponent %d\n".printf (depth)); + writer.write_string ("/Length %d\n".printf (data.length)); + if (filter != null) + writer.write_string ("/Filter /%s\n".printf (filter)); + writer.write_string (">>\n"); + writer.write_string ("stream\n"); + writer.write (data); + writer.write_string ("\n"); + writer.write_string ("endstream\n"); + writer.write_string ("endobj\n"); + + /* Page contents */ + var command = "q\n%s 0 0 %s 0 0 cm\n/Im%d Do\nQ".printf (page_width.format (width_buffer, "%f"), page_height.format (height_buffer, "%f"), i); + writer.write_string ("\n"); + number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (number)); + writer.write_string ("<<\n"); + writer.write_string ("/Length %d\n".printf (command.length + 1)); + writer.write_string (">>\n"); + writer.write_string ("stream\n"); + writer.write_string (command); + writer.write_string ("\n"); + writer.write_string ("endstream\n"); + writer.write_string ("endobj\n"); + } + + /* Info */ + writer.write_string ("\n"); + var info_number = writer.start_object (); + writer.write_string ("%u 0 obj\n".printf (info_number)); + writer.write_string ("<<\n"); + writer.write_string ("/Creator (Simple Scan %s)\n".printf (Config.VERSION)); + writer.write_string (">>\n"); + writer.write_string ("endobj\n"); + + /* Cross-reference table */ + var xref_offset = writer.offset; + writer.write_string ("xref\n"); + writer.write_string ("1 %zu\n".printf (writer.object_offsets.length ())); + foreach (var offset in writer.object_offsets) + writer.write_string ("%010zu 0000 n\n".printf (offset)); + + /* Trailer */ + writer.write_string ("trailer\n"); + writer.write_string ("<<\n"); + writer.write_string ("/Size %zu\n".printf (writer.object_offsets.length ())); + writer.write_string ("/Info %u 0 R\n".printf (info_number)); + writer.write_string ("/Root %u 0 R\n".printf (catalog_number)); + //FIXME: writer.write_string ("/ID [<...> <...>]\n"); + writer.write_string (">>\n"); + writer.write_string ("startxref\n"); + writer.write_string ("%zu\n".printf (xref_offset)); + writer.write_string ("%%%%EOF\n"); + } + + public void save (string type, File file) throws Error + { + if (strcmp (type, "jpeg") == 0) + save_multi_file ("jpeg", file); + else if (strcmp (type, "png") == 0) + save_multi_file ("png", file); + else if (strcmp (type, "tiff") == 0) + save_multi_file ("tiff", file); + else if (strcmp (type, "ps") == 0) + save_ps (file); + else if (strcmp (type, "pdf") == 0) + save_pdf (file); + } + + public void set_needs_saving (bool needs_saving) + { + var needed_saving = this.needs_saving; + this.needs_saving = needs_saving; + if (needed_saving != needs_saving) + needs_saving_changed (); + } + + public bool get_needs_saving () + { + return needs_saving; + } +} + +private class PDFWriter +{ + public size_t offset = 0; + public List<uint> object_offsets; + private FileOutputStream stream; + + public PDFWriter (FileOutputStream stream) + { + this.stream = stream; + } + + public void write (uint8[] data) + { + try + { + stream.write_all (data, null, null); + } + catch (Error e) + { + warning ("Error writing PDF: %s", e.message); + } + offset += data.length; + } + + public void write_string (string text) + { + write ((uint8[]) text.to_utf8 ()); + } + + public uint start_object () + { + object_offsets.append ((uint)offset); + return object_offsets.length (); + } +} + +public class PsWriter +{ + public Cairo.PsSurface surface; + public FileOutputStream stream; + + public PsWriter (FileOutputStream stream) + { + this.stream = stream; + surface = new Cairo.PsSurface.for_stream (write_cairo_data, 0, 0); + } + + private Cairo.Status write_cairo_data (uint8[] data) + { + try + { + stream.write_all (data, null, null); + } + catch (Error e) + { + warning ("Error writing data: %s", e.message); + return Cairo.Status.WRITE_ERROR; + } + + return Cairo.Status.SUCCESS; + } +} diff --git a/src/colord.vapi b/src/colord.vapi new file mode 100644 index 0000000..817673f --- /dev/null +++ b/src/colord.vapi @@ -0,0 +1,17 @@ +[CCode (cprefix = "Cd", lower_case_cprefix = "cd_", cheader_filename = "colord.h")] +namespace Colord { + public class Client : GLib.Object { + public Client (); + public bool connect_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public Device find_device_by_property_sync (string key, string value, GLib.Cancellable? cancellable = null) throws GLib.Error; + } + public class Device : GLib.Object { + public bool connect_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public Profile? get_default_profile (); + } + public class Profile : GLib.Object { + public bool connect_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public string? filename { get; } + } + public const string DEVICE_PROPERTY_SERIAL; +} diff --git a/src/config.vapi b/src/config.vapi new file mode 100644 index 0000000..c326020 --- /dev/null +++ b/src/config.vapi @@ -0,0 +1,10 @@ +[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] +namespace Config +{ + public const string PKGDATADIR; + public const string LOCALE_DIR; + public const string GETTEXT_PACKAGE; + public const string VERSION; + public const string UI_DIR; + public const string ICON_DIR; +} diff --git a/src/jpeglib.vapi b/src/jpeglib.vapi new file mode 100644 index 0000000..3022b5b --- /dev/null +++ b/src/jpeglib.vapi @@ -0,0 +1,57 @@ +[CCode (cheader_filename = "jpeglib.h", cprefix = "jpeg_")] +namespace JPEG { + [CCode (cprefix = "JCS_")] + public enum ColorSpace + { + UNKNOWN, + GRAYSCALE, + RGB, + YCbCr, + CMYK, + YCCK + } + + public ErrorManager std_error (out ErrorManager err); + + [CCode (cname = "struct jpeg_compress_struct", cprefix = "jpeg_", destroy_function = "jpeg_destroy_compress")] + public struct Compress + { + public DestinationManager* dest; + public int image_width; + public int image_height; + public int input_components; + public ColorSpace in_color_space; + public ErrorManager* err; + + public void create_compress (); + public void set_defaults (); + public void start_compress (bool write_all_tables); + public void write_scanlines ([CCode (array_length = false)] uint8*[] scanlines, int num_Lines); + public void finish_compress (); + } + + [CCode (cname = "struct jpeg_error_mgr")] + public struct ErrorManager + { + [CCode (cname = "jpeg_std_error")] + public ErrorManager* std_error (); + } + + [CCode (has_target = false)] + public delegate void InitDestinationFunc (Compress cinfo); + [CCode (has_target = false)] + public delegate bool EmptyOutputBufferFunc (Compress cinfo); + [CCode (has_target = false)] + public delegate void TermDestinationFunc (Compress cinfo); + + [CCode (cname = "struct jpeg_destination_mgr")] + public struct DestinationManager + { + [CCode (array_length = false)] + public unowned uint8[] next_output_byte; + public int free_in_buffer; + public InitDestinationFunc init_destination; + public EmptyOutputBufferFunc empty_output_buffer; + public TermDestinationFunc term_destination; + } +} diff --git a/src/page-view.c b/src/page-view.c index eae49e6..5f916e7 100644 --- a/src/page-view.c +++ b/src/page-view.c @@ -1,7 +1,10 @@ +/* page-view.c generated by valac 0.13.1, the Vala compiler + * generated from page-view.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later @@ -9,1251 +12,2080 @@ * license. */ +#include <glib.h> +#include <glib-object.h> +#include <gdk-pixbuf/gdk-pixdata.h> +#include <float.h> #include <math.h> +#include <gdk/gdk.h> +#include <string.h> +#include <stdlib.h> +#include <cairo.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_CROP_LOCATION (crop_location_get_type ()) + +#define TYPE_PAGE_VIEW (page_view_get_type ()) +#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE_VIEW, PageView)) +#define PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE_VIEW, PageViewClass)) +#define IS_PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE_VIEW)) +#define IS_PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE_VIEW)) +#define PAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE_VIEW, PageViewClass)) + +typedef struct _PageView PageView; +typedef struct _PageViewClass PageViewClass; +typedef struct _PageViewPrivate PageViewPrivate; + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) +#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL))) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +typedef struct _ParamSpecPageView ParamSpecPageView; + +typedef enum { + CROP_LOCATION_NONE = 0, + CROP_LOCATION_MIDDLE, + CROP_LOCATION_TOP, + CROP_LOCATION_BOTTOM, + CROP_LOCATION_LEFT, + CROP_LOCATION_RIGHT, + CROP_LOCATION_TOP_LEFT, + CROP_LOCATION_TOP_RIGHT, + CROP_LOCATION_BOTTOM_LEFT, + CROP_LOCATION_BOTTOM_RIGHT +} CropLocation; + +struct _PageView { + GTypeInstance parent_instance; + volatile int ref_count; + PageViewPrivate * priv; +}; -#include "page-view.h" +struct _PageViewClass { + GTypeClass parent_class; + void (*finalize) (PageView *self); +}; -enum { - CHANGED, - SIZE_CHANGED, - LAST_SIGNAL +typedef enum { + SCAN_DIRECTION_TOP_TO_BOTTOM, + SCAN_DIRECTION_LEFT_TO_RIGHT, + SCAN_DIRECTION_BOTTOM_TO_TOP, + SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _PageViewPrivate { + Page* page; + GdkPixbuf* image; + gboolean selected; + gint border_width; + gboolean update_image; + ScanDirection scan_direction; + gint scan_line; + gint width; + gint height; + gint x_offset; + gint y_offset; + CropLocation crop_location; + gdouble selected_crop_px; + gdouble selected_crop_py; + gint selected_crop_x; + gint selected_crop_y; + gint selected_crop_w; + gint selected_crop_h; + GdkCursorType cursor; + gint animate_n_segments; + gint animate_segment; + guint animate_timeout; }; -static guint signals[LAST_SIGNAL] = { 0, }; -enum { - PROP_0, - PROP_PAGE +struct _ParamSpecPageView { + GParamSpec parent_instance; }; -typedef enum -{ - CROP_NONE = 0, - CROP_MIDDLE, - CROP_TOP, - CROP_BOTTOM, - CROP_LEFT, - CROP_RIGHT, - CROP_TOP_LEFT, - CROP_TOP_RIGHT, - CROP_BOTTOM_LEFT, - CROP_BOTTOM_RIGHT -} CropLocation; -struct PageViewPrivate -{ - /* Page being rendered */ - Page *page; - - /* Image to render at current resolution */ - GdkPixbuf *image; - - /* Border around image */ - gboolean selected; - gint border_width; - - /* True if image needs to be regenerated */ - gboolean update_image; - - /* Direction of currently scanned image */ - ScanDirection scan_direction; - - /* Next scan line to render */ - gint scan_line; - - /* Dimensions of image to generate */ - gint width, height; - - /* Location to place this page */ - gint x, y; - - CropLocation crop_location; - gdouble selected_crop_px, selected_crop_py; - gint selected_crop_x, selected_crop_y; - gint selected_crop_w, selected_crop_h; - - /* Cursor over this page */ - gint cursor; - - gint animate_n_segments, animate_segment; - guint animate_timeout; +static gpointer page_view_parent_class = NULL; + +GType crop_location_get_type (void) G_GNUC_CONST; +gpointer page_view_ref (gpointer instance); +void page_view_unref (gpointer instance); +GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page_view (GValue* value, gpointer v_object); +void value_take_page_view (GValue* value, gpointer v_object); +gpointer value_get_page_view (const GValue* value); +GType page_view_get_type (void) G_GNUC_CONST; +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +GType scan_direction_get_type (void) G_GNUC_CONST; +#define PAGE_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PAGE_VIEW, PageViewPrivate)) +enum { + PAGE_VIEW_DUMMY_PROPERTY }; +PageView* page_view_new (Page* page); +PageView* page_view_construct (GType object_type, Page* page); +static void page_view_page_pixels_changed_cb (PageView* self, Page* p); +static void _page_view_page_pixels_changed_cb_page_pixels_changed (Page* _sender, gpointer self); +static void page_view_page_size_changed_cb (PageView* self, Page* p); +static void _page_view_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self); +static void page_view_page_overlay_changed_cb (PageView* self, Page* p); +static void _page_view_page_overlay_changed_cb_page_crop_changed (Page* _sender, gpointer self); +static void _page_view_page_overlay_changed_cb_page_scan_line_changed (Page* _sender, gpointer self); +static void page_view_scan_direction_changed_cb (PageView* self, Page* p); +static void _page_view_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self); +Page* page_view_get_page (PageView* self); +void page_view_set_selected (PageView* self, gboolean selected); +gboolean page_view_get_selected (PageView* self); +void page_view_set_x_offset (PageView* self, gint offset); +void page_view_set_y_offset (PageView* self, gint offset); +gint page_view_get_x_offset (PageView* self); +gint page_view_get_y_offset (PageView* self); +static guchar page_view_get_sample (PageView* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint sample); +static void page_view_get_pixel (PageView* self, Page* page, gint x, gint y, guchar* pixel, int pixel_length1); +ScanDirection page_get_scan_direction (Page* self); +gint page_get_scan_width (Page* self); +gint page_get_scan_height (Page* self); +gint page_get_depth (Page* self); +gint page_get_n_channels (Page* self); +guchar* page_get_pixels (Page* self, int* result_length1); +gint page_get_rowstride (Page* self); +static void page_view_set_pixel (PageView* self, Page* page, gdouble l, gdouble r, gdouble t, gdouble b, guchar* output, int output_length1, gint offset); +static void page_view_update_preview (PageView* self, Page* page, GdkPixbuf** output_image, gint output_width, gint output_height, ScanDirection scan_direction, gint old_scan_line, gint scan_line); +gint page_get_width (Page* self); +gint page_get_height (Page* self); +gboolean page_has_data (Page* self); +static gint page_view_get_preview_width (PageView* self); +static gint page_view_get_preview_height (PageView* self); +static void page_view_update_page_view (PageView* self); +gint page_get_scan_line (Page* self); +static gint page_view_page_to_screen_x (PageView* self, gint x); +static gint page_view_page_to_screen_y (PageView* self, gint y); +static gint page_view_screen_to_page_x (PageView* self, gint x); +static gint page_view_screen_to_page_y (PageView* self, gint y); +static CropLocation page_view_get_crop_location (PageView* self, gint x, gint y); +gboolean page_has_crop (Page* self); +void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height); +gchar* page_get_named_crop (Page* self); +void page_view_button_press (PageView* self, gint x, gint y); +void page_view_motion (PageView* self, gint x, gint y); +void page_move_crop (Page* self, gint x, gint y); +void page_set_custom_crop (Page* self, gint width, gint height); +void page_view_button_release (PageView* self, gint x, gint y); +GdkCursorType page_view_get_cursor (PageView* self); +static gboolean page_view_animation_cb (PageView* self); +static void page_view_update_animation (PageView* self); +gboolean page_is_scanning (Page* self); +static gboolean _page_view_animation_cb_gsource_func (gpointer self); +void page_view_render (PageView* self, cairo_t* context); +void page_view_set_width (PageView* self, gint width); +void page_view_set_height (PageView* self, gint height); +gint page_view_get_width (PageView* self); +gint page_view_get_height (PageView* self); +static void page_view_finalize (PageView* obj); + + +GType crop_location_get_type (void) { + static volatile gsize crop_location_type_id__volatile = 0; + if (g_once_init_enter (&crop_location_type_id__volatile)) { + static const GEnumValue values[] = {{CROP_LOCATION_NONE, "CROP_LOCATION_NONE", "none"}, {CROP_LOCATION_MIDDLE, "CROP_LOCATION_MIDDLE", "middle"}, {CROP_LOCATION_TOP, "CROP_LOCATION_TOP", "top"}, {CROP_LOCATION_BOTTOM, "CROP_LOCATION_BOTTOM", "bottom"}, {CROP_LOCATION_LEFT, "CROP_LOCATION_LEFT", "left"}, {CROP_LOCATION_RIGHT, "CROP_LOCATION_RIGHT", "right"}, {CROP_LOCATION_TOP_LEFT, "CROP_LOCATION_TOP_LEFT", "top-left"}, {CROP_LOCATION_TOP_RIGHT, "CROP_LOCATION_TOP_RIGHT", "top-right"}, {CROP_LOCATION_BOTTOM_LEFT, "CROP_LOCATION_BOTTOM_LEFT", "bottom-left"}, {CROP_LOCATION_BOTTOM_RIGHT, "CROP_LOCATION_BOTTOM_RIGHT", "bottom-right"}, {0, NULL, NULL}}; + GType crop_location_type_id; + crop_location_type_id = g_enum_register_static ("CropLocation", values); + g_once_init_leave (&crop_location_type_id__volatile, crop_location_type_id); + } + return crop_location_type_id__volatile; +} + + +static gpointer _page_ref0 (gpointer self) { + return self ? page_ref (self) : NULL; +} + + +static void _page_view_page_pixels_changed_cb_page_pixels_changed (Page* _sender, gpointer self) { + page_view_page_pixels_changed_cb (self, _sender); +} + + +static void _page_view_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self) { + page_view_page_size_changed_cb (self, _sender); +} + + +static void _page_view_page_overlay_changed_cb_page_crop_changed (Page* _sender, gpointer self) { + page_view_page_overlay_changed_cb (self, _sender); +} + + +static void _page_view_page_overlay_changed_cb_page_scan_line_changed (Page* _sender, gpointer self) { + page_view_page_overlay_changed_cb (self, _sender); +} + + +static void _page_view_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self) { + page_view_scan_direction_changed_cb (self, _sender); +} + + +PageView* page_view_construct (GType object_type, Page* page) { + PageView* self = NULL; + Page* _tmp0_; + g_return_val_if_fail (page != NULL, NULL); + self = (PageView*) g_type_create_instance (object_type); + _tmp0_ = _page_ref0 (page); + _page_unref0 (self->priv->page); + self->priv->page = _tmp0_; + g_signal_connect (page, "pixels-changed", (GCallback) _page_view_page_pixels_changed_cb_page_pixels_changed, self); + g_signal_connect (page, "size-changed", (GCallback) _page_view_page_size_changed_cb_page_size_changed, self); + g_signal_connect (page, "crop-changed", (GCallback) _page_view_page_overlay_changed_cb_page_crop_changed, self); + g_signal_connect (page, "scan-line-changed", (GCallback) _page_view_page_overlay_changed_cb_page_scan_line_changed, self); + g_signal_connect (page, "scan-direction-changed", (GCallback) _page_view_scan_direction_changed_cb_page_scan_direction_changed, self); + return self; +} + + +PageView* page_view_new (Page* page) { + return page_view_construct (TYPE_PAGE_VIEW, page); +} + -G_DEFINE_TYPE (PageView, page_view, G_TYPE_OBJECT); +Page* page_view_get_page (PageView* self) { + Page* result = NULL; + Page* _tmp0_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = _page_ref0 (self->priv->page); + result = _tmp0_; + return result; +} -PageView * -page_view_new (Page *page) -{ - return g_object_new (PAGE_VIEW_TYPE, "page", page, NULL); +void page_view_set_selected (PageView* self, gboolean selected) { + gboolean _tmp0_ = FALSE; + gboolean _tmp1_ = FALSE; + g_return_if_fail (self != NULL); + if (self->priv->selected) { + _tmp1_ = selected; + } else { + _tmp1_ = FALSE; + } + if (_tmp1_) { + _tmp0_ = TRUE; + } else { + gboolean _tmp2_ = FALSE; + if (!self->priv->selected) { + _tmp2_ = !selected; + } else { + _tmp2_ = FALSE; + } + _tmp0_ = _tmp2_; + } + if (_tmp0_) { + return; + } + self->priv->selected = selected; + g_signal_emit_by_name (self, "changed"); } -Page * -page_view_get_page (PageView *view) -{ - g_return_val_if_fail (view != NULL, NULL); - return view->priv->page; +gboolean page_view_get_selected (PageView* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->selected; + return result; } -void -page_view_set_selected (PageView *view, gboolean selected) -{ - g_return_if_fail (view != NULL); - if ((view->priv->selected && selected) || (!view->priv->selected && !selected)) - return; - view->priv->selected = selected; - g_signal_emit (view, signals[CHANGED], 0); +void page_view_set_x_offset (PageView* self, gint offset) { + g_return_if_fail (self != NULL); + self->priv->x_offset = offset; } -gboolean -page_view_get_selected (PageView *view) -{ - g_return_val_if_fail (view != NULL, FALSE); - return view->priv->selected; +void page_view_set_y_offset (PageView* self, gint offset) { + g_return_if_fail (self != NULL); + self->priv->y_offset = offset; } -void -page_view_set_x_offset (PageView *view, gint offset) -{ - g_return_if_fail (view != NULL); - view->priv->x = offset; +gint page_view_get_x_offset (PageView* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->x_offset; + return result; } -void -page_view_set_y_offset (PageView *view, gint offset) -{ - g_return_if_fail (view != NULL); - view->priv->y = offset; +gint page_view_get_y_offset (PageView* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->y_offset; + return result; } -gint -page_view_get_x_offset (PageView *view) -{ - g_return_val_if_fail (view != NULL, 0); - return view->priv->x; +static guchar page_view_get_sample (PageView* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint sample) { + guchar result = '\0'; + g_return_val_if_fail (self != NULL, '\0'); + result = (guchar) 0xFF; + return result; } -gint -page_view_get_y_offset (PageView *view) -{ - g_return_val_if_fail (view != NULL, 0); - return view->priv->y; +static void page_view_get_pixel (PageView* self, Page* page, gint x, gint y, guchar* pixel, int pixel_length1) { + ScanDirection _tmp0_; + gint _tmp5_; + gint depth; + gint _tmp6_; + gint n_channels; + gint _tmp7_; + guchar* _tmp8_ = NULL; + guchar* pixels; + gint pixels_length1; + gint _pixels_size_; + gint _tmp9_; + gint offset; + gboolean _tmp10_ = FALSE; + guchar _tmp16_; + guchar _tmp17_; + guchar _tmp18_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = page_get_scan_direction (page); + switch (_tmp0_) { + case SCAN_DIRECTION_TOP_TO_BOTTOM: + { + break; + } + case SCAN_DIRECTION_BOTTOM_TO_TOP: + { + gint _tmp1_; + gint _tmp2_; + _tmp1_ = page_get_scan_width (page); + x = (_tmp1_ - x) - 1; + _tmp2_ = page_get_scan_height (page); + y = (_tmp2_ - y) - 1; + break; + } + case SCAN_DIRECTION_LEFT_TO_RIGHT: + { + gint t; + gint _tmp3_; + t = x; + _tmp3_ = page_get_scan_width (page); + x = (_tmp3_ - y) - 1; + y = t; + break; + } + case SCAN_DIRECTION_RIGHT_TO_LEFT: + { + gint t; + gint _tmp4_; + t = x; + x = y; + _tmp4_ = page_get_scan_height (page); + y = (_tmp4_ - t) - 1; + break; + } + default: + break; + } + _tmp5_ = page_get_depth (page); + depth = _tmp5_; + _tmp6_ = page_get_n_channels (page); + n_channels = _tmp6_; + _tmp8_ = page_get_pixels (page, &_tmp7_); + pixels = _tmp8_; + pixels_length1 = _tmp7_; + _pixels_size_ = pixels_length1; + _tmp9_ = page_get_rowstride (page); + offset = _tmp9_ * y; + if (depth == 8) { + _tmp10_ = n_channels == 3; + } else { + _tmp10_ = FALSE; + } + if (_tmp10_) { + gint o; + o = offset + (x * n_channels); + pixel[0] = pixels[o]; + pixel[1] = pixels[o + 1]; + pixel[2] = pixels[o + 2]; + return; + } else { + gboolean _tmp11_ = FALSE; + if (depth == 8) { + _tmp11_ = n_channels == 1; + } else { + _tmp11_ = FALSE; + } + if (_tmp11_) { + pixel[2] = pixels[offset + x]; + pixel[1] = pixel[2]; + pixel[0] = pixel[1]; + return; + } else { + gboolean _tmp12_ = FALSE; + if (depth == 1) { + _tmp12_ = n_channels == 1; + } else { + _tmp12_ = FALSE; + } + if (_tmp12_) { + gint o; + gint _tmp13_ = 0; + o = offset + (x / 8); + if (((gint) (pixels[o] & (0x80 >> (x % 8)))) != 0) { + _tmp13_ = 0x00; + } else { + _tmp13_ = 0xFF; + } + pixel[2] = (guchar) _tmp13_; + pixel[1] = pixel[2]; + pixel[0] = pixel[1]; + return; + } else { + gboolean _tmp14_ = FALSE; + if (depth == 2) { + _tmp14_ = n_channels == 1; + } else { + _tmp14_ = FALSE; + } + if (_tmp14_) { + gint _tmp15_[4] = {0}; + gint block_shift[4]; + gint o; + gint sample; + _tmp15_[0] = 6; + _tmp15_[1] = 4; + _tmp15_[2] = 2; + _tmp15_[3] = 0; + memcpy (block_shift, _tmp15_, 4 * sizeof (gint)); + o = offset + (x / 4); + sample = (pixels[o] >> block_shift[x % 4]) & 0x3; + sample = (sample * 255) / 3; + pixel[2] = (guchar) sample; + pixel[1] = pixel[2]; + pixel[0] = pixel[1]; + return; + } + } + } + } + _tmp16_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, x * n_channels); + pixel[0] = _tmp16_; + _tmp17_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, (x * n_channels) + 1); + pixel[1] = _tmp17_; + _tmp18_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, (x * n_channels) + 2); + pixel[2] = _tmp18_; } -static guchar -get_sample (const guchar *line, gint x, gint depth, gint sample) -{ - // FIXME - return 0xFF; +static void page_view_set_pixel (PageView* self, Page* page, gdouble l, gdouble r, gdouble t, gdouble b, guchar* output, int output_length1, gint offset) { + gint L; + gint R; + gint T; + gint B; + gdouble red; + gdouble green; + gdouble blue; + gboolean _tmp0_ = FALSE; + gboolean _tmp1_ = FALSE; + gboolean _tmp10_ = FALSE; + gboolean _tmp11_ = FALSE; + gboolean _tmp12_ = FALSE; + gboolean _tmp13_ = FALSE; + gdouble scale; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + L = (gint) l; + if (((gdouble) L) != l) { + L++; + } + R = (gint) r; + T = (gint) t; + if (((gdouble) T) != t) { + T++; + } + B = (gint) b; + red = 0.0; + green = 0.0; + blue = 0.0; + if ((r - l) <= 1.0) { + _tmp1_ = ((gint) r) == ((gint) l); + } else { + _tmp1_ = FALSE; + } + if (_tmp1_) { + _tmp0_ = TRUE; + } else { + gboolean _tmp2_ = FALSE; + if ((b - t) <= 1.0) { + _tmp2_ = ((gint) b) == ((gint) t); + } else { + _tmp2_ = FALSE; + } + _tmp0_ = _tmp2_; + } + if (_tmp0_) { + gboolean _tmp3_ = FALSE; + gdouble scale; + if (((gint) l) == ((gint) r)) { + _tmp3_ = TRUE; + } else { + _tmp3_ = ((gint) t) == ((gint) b); + } + if (_tmp3_) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, (gint) l, (gint) t, p, 3); + output[offset] = p[0]; + output[offset + 1] = p[1]; + output[offset + 2] = p[2]; + return; + } + if (L > R) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, R, T - 1, p, 3); + red = red + ((p[0] * (r - l)) * (T - t)); + green = green + ((p[1] * (r - l)) * (T - t)); + blue = blue + ((p[2] * (r - l)) * (T - t)); + { + gint y; + y = T; + { + gboolean _tmp4_; + _tmp4_ = TRUE; + while (TRUE) { + if (!_tmp4_) { + y++; + } + _tmp4_ = FALSE; + if (!(y < B)) { + break; + } + page_view_get_pixel (self, page, R, y, p, 3); + red = red + (p[0] * (r - l)); + green = green + (p[1] * (r - l)); + blue = blue + (p[2] * (r - l)); + } + } + } + page_view_get_pixel (self, page, R, B, p, 3); + red = red + ((p[0] * (r - l)) * (b - B)); + green = green + ((p[1] * (r - l)) * (b - B)); + blue = blue + ((p[2] * (r - l)) * (b - B)); + } else { + guchar p[3] = {0}; + page_view_get_pixel (self, page, L - 1, B, p, 3); + red = red + ((p[0] * (b - t)) * (L - l)); + green = green + ((p[1] * (b - t)) * (L - l)); + blue = blue + ((p[2] * (b - t)) * (L - l)); + { + gint x; + x = L; + { + gboolean _tmp5_; + _tmp5_ = TRUE; + while (TRUE) { + if (!_tmp5_) { + x++; + } + _tmp5_ = FALSE; + if (!(x < R)) { + break; + } + page_view_get_pixel (self, page, x, B, p, 3); + red = red + (p[0] * (b - t)); + green = green + (p[1] * (b - t)); + blue = blue + (p[2] * (b - t)); + } + } + } + page_view_get_pixel (self, page, R, B, p, 3); + red = red + ((p[0] * (b - t)) * (r - R)); + green = green + ((p[1] * (b - t)) * (r - R)); + blue = blue + ((p[2] * (b - t)) * (r - R)); + } + scale = 1.0 / ((r - l) * (b - t)); + output[offset] = (guchar) ((red * scale) + 0.5); + output[offset + 1] = (guchar) ((green * scale) + 0.5); + output[offset + 2] = (guchar) ((blue * scale) + 0.5); + return; + } + { + gint x; + x = L; + { + gboolean _tmp6_; + _tmp6_ = TRUE; + while (TRUE) { + if (!_tmp6_) { + x++; + } + _tmp6_ = FALSE; + if (!(x < R)) { + break; + } + { + gint y; + y = T; + { + gboolean _tmp7_; + _tmp7_ = TRUE; + while (TRUE) { + guchar p[3] = {0}; + if (!_tmp7_) { + y++; + } + _tmp7_ = FALSE; + if (!(y < B)) { + break; + } + page_view_get_pixel (self, page, x, y, p, 3); + red = red + p[0]; + green = green + p[1]; + blue = blue + p[2]; + } + } + } + } + } + } + { + gint x; + x = L; + { + gboolean _tmp8_; + _tmp8_ = TRUE; + while (TRUE) { + if (!_tmp8_) { + x++; + } + _tmp8_ = FALSE; + if (!(x < R)) { + break; + } + if (t != ((gdouble) T)) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, x, T - 1, p, 3); + red = red + (p[0] * (T - t)); + green = green + (p[1] * (T - t)); + blue = blue + (p[2] * (T - t)); + } + if (b != ((gdouble) B)) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, x, B, p, 3); + red = red + (p[0] * (b - B)); + green = green + (p[1] * (b - B)); + blue = blue + (p[2] * (b - B)); + } + } + } + } + { + gint y; + y = T; + { + gboolean _tmp9_; + _tmp9_ = TRUE; + while (TRUE) { + if (!_tmp9_) { + y++; + } + _tmp9_ = FALSE; + if (!(y < B)) { + break; + } + if (l != ((gdouble) L)) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, L - 1, y, p, 3); + red = red + (p[0] * (L - l)); + green = green + (p[1] * (L - l)); + blue = blue + (p[2] * (L - l)); + } + if (r != ((gdouble) R)) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, R, y, p, 3); + red = red + (p[0] * (r - R)); + green = green + (p[1] * (r - R)); + blue = blue + (p[2] * (r - R)); + } + } + } + } + if (l != ((gdouble) L)) { + _tmp10_ = t != ((gdouble) T); + } else { + _tmp10_ = FALSE; + } + if (_tmp10_) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, L - 1, T - 1, p, 3); + red = red + ((p[0] * (L - l)) * (T - t)); + green = green + ((p[1] * (L - l)) * (T - t)); + blue = blue + ((p[2] * (L - l)) * (T - t)); + } + if (r != ((gdouble) R)) { + _tmp11_ = t != ((gdouble) T); + } else { + _tmp11_ = FALSE; + } + if (_tmp11_) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, R, T - 1, p, 3); + red = red + ((p[0] * (r - R)) * (T - t)); + green = green + ((p[1] * (r - R)) * (T - t)); + blue = blue + ((p[2] * (r - R)) * (T - t)); + } + if (r != ((gdouble) R)) { + _tmp12_ = b != ((gdouble) B); + } else { + _tmp12_ = FALSE; + } + if (_tmp12_) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, R, B, p, 3); + red = red + ((p[0] * (r - R)) * (b - B)); + green = green + ((p[1] * (r - R)) * (b - B)); + blue = blue + ((p[2] * (r - R)) * (b - B)); + } + if (l != ((gdouble) L)) { + _tmp13_ = b != ((gdouble) B); + } else { + _tmp13_ = FALSE; + } + if (_tmp13_) { + guchar p[3] = {0}; + page_view_get_pixel (self, page, L - 1, B, p, 3); + red = red + ((p[0] * (L - l)) * (b - B)); + green = green + ((p[1] * (L - l)) * (b - B)); + blue = blue + ((p[2] * (L - l)) * (b - B)); + } + scale = 1.0 / ((r - l) * (b - t)); + output[offset] = (guchar) ((red * scale) + 0.5); + output[offset + 1] = (guchar) ((green * scale) + 0.5); + output[offset + 2] = (guchar) ((blue * scale) + 0.5); } -static void -get_pixel (Page *page, gint x, gint y, guchar *pixel) -{ - gint t, depth, n_channels; - const guchar *p, *line; - - switch (page_get_scan_direction (page)) - { - case TOP_TO_BOTTOM: - break; - case BOTTOM_TO_TOP: - x = page_get_scan_width (page) - x - 1; - y = page_get_scan_height (page) - y - 1; - break; - case LEFT_TO_RIGHT: - t = x; - x = page_get_scan_width (page) - y - 1; - y = t; - break; - case RIGHT_TO_LEFT: - t = x; - x = y; - y = page_get_scan_height (page) - t - 1; - break; - } - - depth = page_get_depth (page); - n_channels = page_get_n_channels (page); - line = page_get_pixels (page) + page_get_rowstride (page) * y; - - /* Optimise for 8 bit images */ - if (depth == 8 && n_channels == 3) { - p = line + x * n_channels; - pixel[0] = p[0]; - pixel[1] = p[1]; - pixel[2] = p[2]; - return; - } - else if (depth == 8 && n_channels == 1) { - p = line + x; - pixel[0] = pixel[1] = pixel[2] = p[0]; - return; - } - - /* Optimise for bitmaps */ - else if (depth == 1 && n_channels == 1) { - p = line + (x / 8); - pixel[0] = pixel[1] = pixel[2] = p[0] & (0x80 >> (x % 8)) ? 0x00 : 0xFF; - return; - } - - /* Optimise for 2 bit images */ - else if (depth == 2 && n_channels == 1) { - gint sample; - gint block_shift[4] = { 6, 4, 2, 0 }; - - p = line + (x / 4); - sample = (p[0] >> block_shift[x % 4]) & 0x3; - sample = sample * 255 / 3; - - pixel[0] = pixel[1] = pixel[2] = sample; - return; - } - - /* Use slow method */ - pixel[0] = get_sample (line, x, depth, x * n_channels); - pixel[0] = get_sample (line, x, depth, x * n_channels + 1); - pixel[0] = get_sample (line, x, depth, x * n_channels + 2); +static void page_view_update_preview (PageView* self, Page* page, GdkPixbuf** output_image, gint output_width, gint output_height, ScanDirection scan_direction, gint old_scan_line, gint scan_line) { + gint _tmp0_; + gint input_width; + gint _tmp1_; + gint input_height; + gint L = 0; + gint R = 0; + gint T = 0; + gint B = 0; + gboolean _tmp2_ = FALSE; + gboolean _tmp3_ = FALSE; + guint8* _tmp7_ = NULL; + guchar* output; + gint output_length1; + gint _output_size_; + gint _tmp8_; + gint output_rowstride; + gint _tmp9_; + gint output_n_channels; + gboolean _tmp10_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = page_get_width (page); + input_width = _tmp0_; + _tmp1_ = page_get_height (page); + input_height = _tmp1_; + if ((*output_image) == NULL) { + _tmp3_ = TRUE; + } else { + gint _tmp4_; + _tmp4_ = gdk_pixbuf_get_width (*output_image); + _tmp3_ = _tmp4_ != output_width; + } + if (_tmp3_) { + _tmp2_ = TRUE; + } else { + gint _tmp5_; + _tmp5_ = gdk_pixbuf_get_height (*output_image); + _tmp2_ = _tmp5_ != output_height; + } + if (_tmp2_) { + GdkPixbuf* _tmp6_ = NULL; + _tmp6_ = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, output_width, output_height); + _g_object_unref0 (*output_image); + *output_image = _tmp6_; + L = 0; + R = output_width - 1; + T = 0; + B = output_height - 1; + } else { + switch (scan_direction) { + case SCAN_DIRECTION_TOP_TO_BOTTOM: + { + L = 0; + R = output_width - 1; + T = (gint) ((((gdouble) old_scan_line) * output_height) / input_height); + B = (gint) (((((gdouble) scan_line) * output_height) / input_height) + 0.5); + break; + } + case SCAN_DIRECTION_LEFT_TO_RIGHT: + { + L = (gint) ((((gdouble) old_scan_line) * output_width) / input_width); + R = (gint) (((((gdouble) scan_line) * output_width) / input_width) + 0.5); + T = 0; + B = output_height - 1; + break; + } + case SCAN_DIRECTION_BOTTOM_TO_TOP: + { + L = 0; + R = output_width - 1; + T = (gint) ((((gdouble) (input_height - scan_line)) * output_height) / input_height); + B = (gint) (((((gdouble) (input_height - old_scan_line)) * output_height) / input_height) + 0.5); + break; + } + case SCAN_DIRECTION_RIGHT_TO_LEFT: + { + L = (gint) ((((gdouble) (input_width - scan_line)) * output_width) / input_width); + R = (gint) (((((gdouble) (input_width - old_scan_line)) * output_width) / input_width) + 0.5); + T = 0; + B = output_height - 1; + break; + } + default: + { + T = 0; + B = T; + R = B; + L = R; + break; + } + } + } + if (R >= output_width) { + R = output_width - 1; + } + if (B >= output_height) { + B = output_height - 1; + } + g_return_if_fail (L >= 0); + g_return_if_fail (R < output_width); + g_return_if_fail (T >= 0); + g_return_if_fail (B < output_height); + g_return_if_fail ((*output_image) != NULL); + _tmp7_ = gdk_pixbuf_get_pixels (*output_image); + output = _tmp7_; + output_length1 = -1; + _output_size_ = output_length1; + _tmp8_ = gdk_pixbuf_get_rowstride (*output_image); + output_rowstride = _tmp8_; + _tmp9_ = gdk_pixbuf_get_n_channels (*output_image); + output_n_channels = _tmp9_; + _tmp10_ = page_has_data (page); + if (!_tmp10_) { + { + gint x; + x = L; + { + gboolean _tmp11_; + _tmp11_ = TRUE; + while (TRUE) { + if (!_tmp11_) { + x++; + } + _tmp11_ = FALSE; + if (!(x <= R)) { + break; + } + { + gint y; + y = T; + { + gboolean _tmp12_; + _tmp12_ = TRUE; + while (TRUE) { + gint o; + if (!_tmp12_) { + y++; + } + _tmp12_ = FALSE; + if (!(y <= B)) { + break; + } + o = (output_rowstride * y) + (x * output_n_channels); + output[o + 2] = (guchar) 0xFF; + output[o + 1] = output[o + 2]; + output[o] = output[o + 1]; + } + } + } + } + } + } + return; + } + { + gint x; + x = L; + { + gboolean _tmp13_; + _tmp13_ = TRUE; + while (TRUE) { + gdouble l; + gdouble r; + if (!_tmp13_) { + x++; + } + _tmp13_ = FALSE; + if (!(x <= R)) { + break; + } + l = (((gdouble) x) * input_width) / output_width; + r = (((gdouble) (x + 1)) * input_width) / output_width; + { + gint y; + y = T; + { + gboolean _tmp14_; + _tmp14_ = TRUE; + while (TRUE) { + gdouble t; + gdouble b; + if (!_tmp14_) { + y++; + } + _tmp14_ = FALSE; + if (!(y <= B)) { + break; + } + t = (((gdouble) y) * input_height) / output_height; + b = (((gdouble) (y + 1)) * input_height) / output_height; + page_view_set_pixel (self, page, l, r, t, b, output, output_length1, (output_rowstride * y) + (x * output_n_channels)); + } + } + } + } + } + } } -static void -set_pixel (Page *page, - double l, double r, double t, double b, guchar *pixel) -{ - gint x, y; - gint L, R, T, B; - guchar p[3]; - double scale, red, green, blue; - - /* Decimation: - * - * Target pixel is defined by (t,l)-(b,r) - * It touches 16 pixels in original image - * It completely covers 4 pixels in original image (T,L)-(B,R) - * Add covered pixels and add weighted partially covered pixels. - * Divide by total area. - * - * l L R r - * +-----+-----+-----+-----+ - * | | | | | - * t | +--+-----+-----+---+ | - * T +--+--+-----+-----+---+-+ - * | | | | | | | - * | | | | | | | - * +--+--+-----+-----+---+-+ - * | | | | | | | - * | | | | | | | - * B +--+--+-----+-----+---+-+ - * | | | | | | | - * b | +--+-----+-----+---+ | - * +-----+-----+-----+-----+ - * - * - * Interpolation: - * - * l r - * +-----+-----+-----+-----+ - * | | | | | - * | | | | | - * +-----+-----+-----+-----+ - * t | | +-+--+ | | - * | | | | | | | - * +-----+---+-+--+--+-----+ - * b | | +-+--+ | | - * | | | | | - * +-----+-----+-----+-----+ - * | | | | | - * | | | | | - * +-----+-----+-----+-----+ - * - * Same again, just no completely covered pixels. - */ - - L = l; - if (L != l) - L++; - R = r; - T = t; - if (T != t) - T++; - B = b; - - red = green = blue = 0.0; - - /* Target can fit inside one source pixel - * +-----+ - * | | - * | +--+| +-----+-----+ +-----+ +-----+ +-----+ - * +-+--++ or | +-++ | or | +-+ | or | +--+| or | +--+ - * | +--+| | +-++ | | +-+ | | | || | | | - * | | +-----+-----+ +-----+ +-+--++ +--+--+ - * +-----+ - */ - if ((r - l <= 1.0 && (gint)r == (gint)l) || (b - t <= 1.0 && (gint)b == (gint)t)) { - /* Inside */ - if ((gint)l == (gint)r || (gint)t == (gint)b) { - get_pixel (page, (gint)l, (gint)t, p); - pixel[0] = p[0]; - pixel[1] = p[1]; - pixel[2] = p[2]; - return; - } - - /* Stradling horizontal edge */ - if (L > R) { - get_pixel (page, R, T-1, p); - red += p[0] * (r-l)*(T-t); - green += p[1] * (r-l)*(T-t); - blue += p[2] * (r-l)*(T-t); - for (y = T; y < B; y++) { - get_pixel (page, R, y, p); - red += p[0] * (r-l); - green += p[1] * (r-l); - blue += p[2] * (r-l); - } - get_pixel (page, R, B, p); - red += p[0] * (r-l)*(b-B); - green += p[1] * (r-l)*(b-B); - blue += p[2] * (r-l)*(b-B); - } - /* Stradling vertical edge */ - else { - get_pixel (page, L - 1, B, p); - red += p[0] * (b-t)*(L-l); - green += p[1] * (b-t)*(L-l); - blue += p[2] * (b-t)*(L-l); - for (x = L; x < R; x++) { - get_pixel (page, x, B, p); - red += p[0] * (b-t); - green += p[1] * (b-t); - blue += p[2] * (b-t); - } - get_pixel (page, R, B, p); - red += p[0] * (b-t)*(r-R); - green += p[1] * (b-t)*(r-R); - blue += p[2] * (b-t)*(r-R); - } - - scale = 1.0 / ((r - l) * (b - t)); - pixel[0] = (guchar)(red * scale + 0.5); - pixel[1] = (guchar)(green * scale + 0.5); - pixel[2] = (guchar)(blue * scale + 0.5); - return; - } - - /* Add the middle pixels */ - for (x = L; x < R; x++) { - for (y = T; y < B; y++) { - get_pixel (page, x, y, p); - red += p[0]; - green += p[1]; - blue += p[2]; - } - } - - /* Add the weighted top and bottom pixels */ - for (x = L; x < R; x++) { - if (t != T) { - get_pixel (page, x, T - 1, p); - red += p[0] * (T - t); - green += p[1] * (T - t); - blue += p[2] * (T - t); - } - - if (b != B) { - get_pixel (page, x, B, p); - red += p[0] * (b - B); - green += p[1] * (b - B); - blue += p[2] * (b - B); - } - } - - /* Add the left and right pixels */ - for (y = T; y < B; y++) { - if (l != L) { - get_pixel (page, L - 1, y, p); - red += p[0] * (L - l); - green += p[1] * (L - l); - blue += p[2] * (L - l); - } - - if (r != R) { - get_pixel (page, R, y, p); - red += p[0] * (r - R); - green += p[1] * (r - R); - blue += p[2] * (r - R); - } - } - - /* Add the corner pixels */ - if (l != L && t != T) { - get_pixel (page, L - 1, T - 1, p); - red += p[0] * (L - l)*(T - t); - green += p[1] * (L - l)*(T - t); - blue += p[2] * (L - l)*(T - t); - } - if (r != R && t != T) { - get_pixel (page, R, T - 1, p); - red += p[0] * (r - R)*(T - t); - green += p[1] * (r - R)*(T - t); - blue += p[2] * (r - R)*(T - t); - } - if (r != R && b != B) { - get_pixel (page, R, B, p); - red += p[0] * (r - R)*(b - B); - green += p[1] * (r - R)*(b - B); - blue += p[2] * (r - R)*(b - B); - } - if (l != L && b != B) { - get_pixel (page, L - 1, B, p); - red += p[0] * (L - l)*(b - B); - green += p[1] * (L - l)*(b - B); - blue += p[2] * (L - l)*(b - B); - } - - /* Scale pixel values and clamp in range [0, 255] */ - scale = 1.0 / ((r - l) * (b - t)); - pixel[0] = (guchar)(red * scale + 0.5); - pixel[1] = (guchar)(green * scale + 0.5); - pixel[2] = (guchar)(blue * scale + 0.5); +static gint page_view_get_preview_width (PageView* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->width - (self->priv->border_width * 2); + return result; } -static void -update_preview (Page *page, - GdkPixbuf **output_image, gint output_width, gint output_height, - ScanDirection scan_direction, gint old_scan_line, gint scan_line) -{ - guchar *output; - gint input_width, input_height; - gint output_rowstride, output_n_channels; - gint x, y; - gint L, R, T, B; - - input_width = page_get_width (page); - input_height = page_get_height (page); - - /* Create new image if one does not exist or has changed size */ - if (!*output_image || - gdk_pixbuf_get_width (*output_image) != output_width || - gdk_pixbuf_get_height (*output_image) != output_height) { - if (*output_image) - g_object_unref (*output_image); - *output_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - FALSE, - 8, - output_width, - output_height); - - /* Update entire image */ - L = 0; - R = output_width - 1; - T = 0; - B = output_height - 1; - } - /* Otherwise only update changed area */ - else { - switch (scan_direction) { - case TOP_TO_BOTTOM: - L = 0; - R = output_width - 1; - T = (gint)((double)old_scan_line * output_height / input_height); - B = (gint)((double)scan_line * output_height / input_height + 0.5); - break; - case LEFT_TO_RIGHT: - L = (gint)((double)old_scan_line * output_width / input_width); - R = (gint)((double)scan_line * output_width / input_width + 0.5); - T = 0; - B = output_height - 1; - break; - case BOTTOM_TO_TOP: - L = 0; - R = output_width - 1; - T = (gint)((double)(input_height - scan_line) * output_height / input_height); - B = (gint)((double)(input_height - old_scan_line) * output_height / input_height + 0.5); - break; - case RIGHT_TO_LEFT: - L = (gint)((double)(input_width - scan_line) * output_width / input_width); - R = (gint)((double)(input_width - old_scan_line) * output_width / input_width + 0.5); - T = 0; - B = output_height - 1; - break; - default: - L = R = B = T = 0; - break; - } - } - - /* FIXME: There's an off by one error in there somewhere... */ - if (R >= output_width) - R = output_width - 1; - if (B >= output_height) - B = output_height - 1; - - g_return_if_fail (L >= 0); - g_return_if_fail (R < output_width); - g_return_if_fail (T >= 0); - g_return_if_fail (B < output_height); - g_return_if_fail (*output_image != NULL); - - output = gdk_pixbuf_get_pixels (*output_image); - output_rowstride = gdk_pixbuf_get_rowstride (*output_image); - output_n_channels = gdk_pixbuf_get_n_channels (*output_image); - - if (!page_has_data (page)) { - for (x = L; x <= R; x++) - for (y = T; y <= B; y++) { - guchar *pixel; - pixel = output + output_rowstride * y + x * output_n_channels; - pixel[0] = pixel[1] = pixel[2] = 0xFF; - } - return; - } - - /* Update changed area */ - for (x = L; x <= R; x++) { - double l, r; - - l = (double)x * input_width / output_width; - r = (double)(x + 1) * input_width / output_width; - - for (y = T; y <= B; y++) { - double t, b; - - t = (double)y * input_height / output_height; - b = (double)(y + 1) * input_height / output_height; - - set_pixel (page, - l, r, t, b, - output + output_rowstride * y + x * output_n_channels); - } - } +static gint page_view_get_preview_height (PageView* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->height - (self->priv->border_width * 2); + return result; } -static gint -get_preview_width (PageView *view) -{ - return view->priv->width - view->priv->border_width * 2; +static void page_view_update_page_view (PageView* self) { + gint old_scan_line; + gint _tmp0_; + gint scan_line; + ScanDirection _tmp1_; + ScanDirection left_steps; + gboolean _tmp2_ = FALSE; + ScanDirection _tmp3_; + gint _tmp4_; + gint _tmp5_; + ScanDirection _tmp6_; + g_return_if_fail (self != NULL); + if (!self->priv->update_image) { + return; + } + old_scan_line = self->priv->scan_line; + _tmp0_ = page_get_scan_line (self->priv->page); + scan_line = _tmp0_; + _tmp1_ = page_get_scan_direction (self->priv->page); + left_steps = self->priv->scan_direction - _tmp1_; + if (left_steps != 0) { + _tmp2_ = self->priv->image != NULL; + } else { + _tmp2_ = FALSE; + } + if (_tmp2_) { + _g_object_unref0 (self->priv->image); + self->priv->image = NULL; + } + _tmp3_ = page_get_scan_direction (self->priv->page); + self->priv->scan_direction = _tmp3_; + _tmp4_ = page_view_get_preview_width (self); + _tmp5_ = page_view_get_preview_height (self); + _tmp6_ = page_get_scan_direction (self->priv->page); + page_view_update_preview (self, self->priv->page, &self->priv->image, _tmp4_, _tmp5_, _tmp6_, old_scan_line, scan_line); + self->priv->update_image = FALSE; + self->priv->scan_line = scan_line; } -static gint -get_preview_height (PageView *view) -{ - return view->priv->height - view->priv->border_width * 2; +static gint page_view_page_to_screen_x (PageView* self, gint x) { + gint result = 0; + gint _tmp0_; + gint _tmp1_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = page_view_get_preview_width (self); + _tmp1_ = page_get_width (self->priv->page); + result = (gint) (((((gdouble) x) * _tmp0_) / _tmp1_) + 0.5); + return result; } -static void -update_page_view (PageView *view) -{ - gint old_scan_line, scan_line, left_steps; +static gint page_view_page_to_screen_y (PageView* self, gint y) { + gint result = 0; + gint _tmp0_; + gint _tmp1_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = page_view_get_preview_height (self); + _tmp1_ = page_get_height (self->priv->page); + result = (gint) (((((gdouble) y) * _tmp0_) / _tmp1_) + 0.5); + return result; +} + - if (!view->priv->update_image) - return; +static gint page_view_screen_to_page_x (PageView* self, gint x) { + gint result = 0; + gint _tmp0_; + gint _tmp1_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = page_get_width (self->priv->page); + _tmp1_ = page_view_get_preview_width (self); + result = (gint) (((((gdouble) x) * _tmp0_) / _tmp1_) + 0.5); + return result; +} - old_scan_line = view->priv->scan_line; - scan_line = page_get_scan_line (view->priv->page); - /* Delete old image if scan direction changed */ - left_steps = view->priv->scan_direction - page_get_scan_direction (view->priv->page); - if (left_steps && view->priv->image) { - g_object_unref (view->priv->image); - view->priv->image = NULL; - } - view->priv->scan_direction = page_get_scan_direction (view->priv->page); +static gint page_view_screen_to_page_y (PageView* self, gint y) { + gint result = 0; + gint _tmp0_; + gint _tmp1_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = page_get_height (self->priv->page); + _tmp1_ = page_view_get_preview_height (self); + result = (gint) (((((gdouble) y) * _tmp0_) / _tmp1_) + 0.5); + return result; +} - update_preview (view->priv->page, - &view->priv->image, - get_preview_width (view), - get_preview_height (view), - page_get_scan_direction (view->priv->page), old_scan_line, scan_line); - view->priv->update_image = FALSE; - view->priv->scan_line = scan_line; +static CropLocation page_view_get_crop_location (PageView* self, gint x, gint y) { + CropLocation result = 0; + gboolean _tmp0_; + gint cx = 0; + gint cy = 0; + gint cw = 0; + gint ch = 0; + gint _tmp1_; + gint _tmp2_; + gint _tmp3_; + gint _tmp4_; + gint _tmp5_; + gint dx; + gint _tmp6_; + gint dy; + gint _tmp7_; + gint dw; + gint _tmp8_; + gint dh; + gint ix; + gint iy; + gboolean _tmp9_ = FALSE; + gboolean _tmp10_ = FALSE; + gboolean _tmp11_ = FALSE; + gchar* _tmp12_ = NULL; + gchar* name; + gint crop_border; + gboolean _tmp13_ = FALSE; + gboolean _tmp14_ = FALSE; + gboolean _tmp15_ = FALSE; + gboolean _tmp16_ = FALSE; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = page_has_crop (self->priv->page); + if (!_tmp0_) { + result = 0; + return result; + } + page_get_crop (self->priv->page, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_); + cx = _tmp1_; + cy = _tmp2_; + cw = _tmp3_; + ch = _tmp4_; + _tmp5_ = page_view_page_to_screen_x (self, cx); + dx = _tmp5_; + _tmp6_ = page_view_page_to_screen_y (self, cy); + dy = _tmp6_; + _tmp7_ = page_view_page_to_screen_x (self, cw); + dw = _tmp7_; + _tmp8_ = page_view_page_to_screen_y (self, ch); + dh = _tmp8_; + ix = x - dx; + iy = y - dy; + if (ix < 0) { + _tmp11_ = TRUE; + } else { + _tmp11_ = ix > dw; + } + if (_tmp11_) { + _tmp10_ = TRUE; + } else { + _tmp10_ = iy < 0; + } + if (_tmp10_) { + _tmp9_ = TRUE; + } else { + _tmp9_ = iy > dh; + } + if (_tmp9_) { + result = CROP_LOCATION_NONE; + return result; + } + _tmp12_ = page_get_named_crop (self->priv->page); + name = _tmp12_; + if (name != NULL) { + result = CROP_LOCATION_MIDDLE; + _g_free0 (name); + return result; + } + crop_border = 20; + if (dw < (crop_border * 3)) { + crop_border = dw / 3; + } + if (dh < (crop_border * 3)) { + crop_border = dh / 3; + } + if (ix < crop_border) { + _tmp13_ = iy < crop_border; + } else { + _tmp13_ = FALSE; + } + if (_tmp13_) { + result = CROP_LOCATION_TOP_LEFT; + _g_free0 (name); + return result; + } + if (ix > (dw - crop_border)) { + _tmp14_ = iy < crop_border; + } else { + _tmp14_ = FALSE; + } + if (_tmp14_) { + result = CROP_LOCATION_TOP_RIGHT; + _g_free0 (name); + return result; + } + if (ix < crop_border) { + _tmp15_ = iy > (dh - crop_border); + } else { + _tmp15_ = FALSE; + } + if (_tmp15_) { + result = CROP_LOCATION_BOTTOM_LEFT; + _g_free0 (name); + return result; + } + if (ix > (dw - crop_border)) { + _tmp16_ = iy > (dh - crop_border); + } else { + _tmp16_ = FALSE; + } + if (_tmp16_) { + result = CROP_LOCATION_BOTTOM_RIGHT; + _g_free0 (name); + return result; + } + if (ix < crop_border) { + result = CROP_LOCATION_LEFT; + _g_free0 (name); + return result; + } + if (ix > (dw - crop_border)) { + result = CROP_LOCATION_RIGHT; + _g_free0 (name); + return result; + } + if (iy < crop_border) { + result = CROP_LOCATION_TOP; + _g_free0 (name); + return result; + } + if (iy > (dh - crop_border)) { + result = CROP_LOCATION_BOTTOM; + _g_free0 (name); + return result; + } + result = CROP_LOCATION_MIDDLE; + _g_free0 (name); + return result; } -static gint -page_to_screen_x (PageView *view, gint x) -{ - return (double) x * get_preview_width (view) / page_get_width (view->priv->page) + 0.5; +void page_view_button_press (PageView* self, gint x, gint y) { + CropLocation location = 0; + CropLocation _tmp0_; + g_return_if_fail (self != NULL); + _tmp0_ = page_view_get_crop_location (self, x, y); + location = _tmp0_; + if (location != CROP_LOCATION_NONE) { + gint _tmp1_; + gint _tmp2_; + gint _tmp3_; + gint _tmp4_; + self->priv->crop_location = location; + self->priv->selected_crop_px = (gdouble) x; + self->priv->selected_crop_py = (gdouble) y; + page_get_crop (self->priv->page, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_); + self->priv->selected_crop_x = _tmp1_; + self->priv->selected_crop_y = _tmp2_; + self->priv->selected_crop_w = _tmp3_; + self->priv->selected_crop_h = _tmp4_; + } } -static gint -page_to_screen_y (PageView *view, gint y) -{ - return (double) y * get_preview_height (view) / page_get_height (view->priv->page) + 0.5; +void page_view_motion (PageView* self, gint x, gint y) { + CropLocation _tmp0_; + CropLocation location; + GdkCursorType cursor = 0; + gint _tmp1_; + gint pw; + gint _tmp2_; + gint ph; + gint cx = 0; + gint cy = 0; + gint cw = 0; + gint ch = 0; + gint _tmp3_; + gint _tmp4_; + gint _tmp5_; + gint _tmp6_; + gint _tmp7_; + gint dx; + gint _tmp8_; + gint dy; + gint new_x; + gint new_y; + gint new_w; + gint new_h; + gint _tmp9_; + gint min_size; + gboolean _tmp10_ = FALSE; + gboolean _tmp11_ = FALSE; + gboolean _tmp12_ = FALSE; + gboolean _tmp13_ = FALSE; + gboolean _tmp14_ = FALSE; + gboolean _tmp15_ = FALSE; + gboolean _tmp16_ = FALSE; + gboolean _tmp17_ = FALSE; + gboolean _tmp18_ = FALSE; + gboolean _tmp19_ = FALSE; + gboolean _tmp20_ = FALSE; + gboolean _tmp21_ = FALSE; + gboolean _tmp22_ = FALSE; + gboolean _tmp23_ = FALSE; + gboolean _tmp24_ = FALSE; + gboolean _tmp25_ = FALSE; + gboolean _tmp26_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = page_view_get_crop_location (self, x, y); + location = _tmp0_; + switch (location) { + case CROP_LOCATION_MIDDLE: + { + cursor = GDK_HAND1; + break; + } + case CROP_LOCATION_TOP: + { + cursor = GDK_TOP_SIDE; + break; + } + case CROP_LOCATION_BOTTOM: + { + cursor = GDK_BOTTOM_SIDE; + break; + } + case CROP_LOCATION_LEFT: + { + cursor = GDK_LEFT_SIDE; + break; + } + case CROP_LOCATION_RIGHT: + { + cursor = GDK_RIGHT_SIDE; + break; + } + case CROP_LOCATION_TOP_LEFT: + { + cursor = GDK_TOP_LEFT_CORNER; + break; + } + case CROP_LOCATION_TOP_RIGHT: + { + cursor = GDK_TOP_RIGHT_CORNER; + break; + } + case CROP_LOCATION_BOTTOM_LEFT: + { + cursor = GDK_BOTTOM_LEFT_CORNER; + break; + } + case CROP_LOCATION_BOTTOM_RIGHT: + { + cursor = GDK_BOTTOM_RIGHT_CORNER; + break; + } + default: + { + cursor = GDK_ARROW; + break; + } + } + if (self->priv->crop_location == CROP_LOCATION_NONE) { + self->priv->cursor = cursor; + return; + } + _tmp1_ = page_get_width (self->priv->page); + pw = _tmp1_; + _tmp2_ = page_get_height (self->priv->page); + ph = _tmp2_; + page_get_crop (self->priv->page, &_tmp3_, &_tmp4_, &_tmp5_, &_tmp6_); + cx = _tmp3_; + cy = _tmp4_; + cw = _tmp5_; + ch = _tmp6_; + _tmp7_ = page_view_screen_to_page_x (self, x - ((gint) self->priv->selected_crop_px)); + dx = _tmp7_; + _tmp8_ = page_view_screen_to_page_y (self, y - ((gint) self->priv->selected_crop_py)); + dy = _tmp8_; + new_x = self->priv->selected_crop_x; + new_y = self->priv->selected_crop_y; + new_w = self->priv->selected_crop_w; + new_h = self->priv->selected_crop_h; + _tmp9_ = page_view_screen_to_page_x (self, 15); + min_size = _tmp9_; + if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) { + _tmp11_ = TRUE; + } else { + _tmp11_ = self->priv->crop_location == CROP_LOCATION_LEFT; + } + if (_tmp11_) { + _tmp10_ = TRUE; + } else { + _tmp10_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT; + } + if (_tmp10_) { + if (dx > (new_w - min_size)) { + dx = new_w - min_size; + } + if ((new_x + dx) < 0) { + dx = -new_x; + } + } + if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) { + _tmp13_ = TRUE; + } else { + _tmp13_ = self->priv->crop_location == CROP_LOCATION_TOP; + } + if (_tmp13_) { + _tmp12_ = TRUE; + } else { + _tmp12_ = self->priv->crop_location == CROP_LOCATION_TOP_RIGHT; + } + if (_tmp12_) { + if (dy > (new_h - min_size)) { + dy = new_h - min_size; + } + if ((new_y + dy) < 0) { + dy = -new_y; + } + } + if (self->priv->crop_location == CROP_LOCATION_TOP_RIGHT) { + _tmp15_ = TRUE; + } else { + _tmp15_ = self->priv->crop_location == CROP_LOCATION_RIGHT; + } + if (_tmp15_) { + _tmp14_ = TRUE; + } else { + _tmp14_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT; + } + if (_tmp14_) { + if (dx < (min_size - new_w)) { + dx = min_size - new_w; + } + if (((new_x + new_w) + dx) > pw) { + dx = (pw - new_x) - new_w; + } + } + if (self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT) { + _tmp17_ = TRUE; + } else { + _tmp17_ = self->priv->crop_location == CROP_LOCATION_BOTTOM; + } + if (_tmp17_) { + _tmp16_ = TRUE; + } else { + _tmp16_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT; + } + if (_tmp16_) { + if (dy < (min_size - new_h)) { + dy = min_size - new_h; + } + if (((new_y + new_h) + dy) > ph) { + dy = (ph - new_y) - new_h; + } + } + if (self->priv->crop_location == CROP_LOCATION_MIDDLE) { + if (((new_x + dx) + new_w) > pw) { + dx = (pw - new_x) - new_w; + } + if ((new_x + dx) < 0) { + dx = -new_x; + } + if (((new_y + dy) + new_h) > ph) { + dy = (ph - new_y) - new_h; + } + if ((new_y + dy) < 0) { + dy = -new_y; + } + } + if (self->priv->crop_location == CROP_LOCATION_MIDDLE) { + new_x = new_x + dx; + new_y = new_y + dy; + } + if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) { + _tmp19_ = TRUE; + } else { + _tmp19_ = self->priv->crop_location == CROP_LOCATION_LEFT; + } + if (_tmp19_) { + _tmp18_ = TRUE; + } else { + _tmp18_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT; + } + if (_tmp18_) { + new_x = new_x + dx; + new_w = new_w - dx; + } + if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) { + _tmp21_ = TRUE; + } else { + _tmp21_ = self->priv->crop_location == CROP_LOCATION_TOP; + } + if (_tmp21_) { + _tmp20_ = TRUE; + } else { + _tmp20_ = self->priv->crop_location == CROP_LOCATION_TOP_RIGHT; + } + if (_tmp20_) { + new_y = new_y + dy; + new_h = new_h - dy; + } + if (self->priv->crop_location == CROP_LOCATION_TOP_RIGHT) { + _tmp23_ = TRUE; + } else { + _tmp23_ = self->priv->crop_location == CROP_LOCATION_RIGHT; + } + if (_tmp23_) { + _tmp22_ = TRUE; + } else { + _tmp22_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT; + } + if (_tmp22_) { + new_w = new_w + dx; + } + if (self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT) { + _tmp25_ = TRUE; + } else { + _tmp25_ = self->priv->crop_location == CROP_LOCATION_BOTTOM; + } + if (_tmp25_) { + _tmp24_ = TRUE; + } else { + _tmp24_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT; + } + if (_tmp24_) { + new_h = new_h + dy; + } + page_move_crop (self->priv->page, new_x, new_y); + if (new_w != cw) { + _tmp26_ = TRUE; + } else { + _tmp26_ = new_h != ch; + } + if (_tmp26_) { + page_set_custom_crop (self->priv->page, new_w, new_h); + } } -static gint -screen_to_page_x (PageView *view, gint x) -{ - return (double) x * page_get_width (view->priv->page) / get_preview_width (view) + 0.5; +void page_view_button_release (PageView* self, gint x, gint y) { + g_return_if_fail (self != NULL); + self->priv->crop_location = CROP_LOCATION_NONE; + g_signal_emit_by_name (self, "changed"); } -static gint -screen_to_page_y (PageView *view, gint y) -{ - return (double) y * page_get_height (view->priv->page) / get_preview_height (view) + 0.5; +GdkCursorType page_view_get_cursor (PageView* self) { + GdkCursorType result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->cursor; + return result; } -static CropLocation -get_crop_location (PageView *view, gint x, gint y) -{ - gint cx, cy, cw, ch; - gint dx, dy, dw, dh; - gint ix, iy; - gint crop_border = 20; - gchar *name; - - if (!page_has_crop (view->priv->page)) - return 0; - - page_get_crop (view->priv->page, &cx, &cy, &cw, &ch); - dx = page_to_screen_x (view, cx); - dy = page_to_screen_y (view, cy); - dw = page_to_screen_x (view, cw); - dh = page_to_screen_y (view, ch); - ix = x - dx; - iy = y - dy; - - if (ix < 0 || ix > dw || iy < 0 || iy > dh) - return CROP_NONE; - - /* Can't resize named crops */ - name = page_get_named_crop (view->priv->page); - if (name != NULL) { - g_free (name); - return CROP_MIDDLE; - } - - /* Adjust borders so can select */ - if (dw < crop_border * 3) - crop_border = dw / 3; - if (dh < crop_border * 3) - crop_border = dh / 3; - - /* Top left */ - if (ix < crop_border && iy < crop_border) - return CROP_TOP_LEFT; - /* Top right */ - if (ix > dw - crop_border && iy < crop_border) - return CROP_TOP_RIGHT; - /* Bottom left */ - if (ix < crop_border && iy > dh - crop_border) - return CROP_BOTTOM_LEFT; - /* Bottom right */ - if (ix > dw - crop_border && iy > dh - crop_border) - return CROP_BOTTOM_RIGHT; - - /* Left */ - if (ix < crop_border) - return CROP_LEFT; - /* Right */ - if (ix > dw - crop_border) - return CROP_RIGHT; - /* Top */ - if (iy < crop_border) - return CROP_TOP; - /* Bottom */ - if (iy > dh - crop_border) - return CROP_BOTTOM; - - /* In the middle */ - return CROP_MIDDLE; +static gboolean page_view_animation_cb (PageView* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + self->priv->animate_segment = (self->priv->animate_segment + 1) % self->priv->animate_n_segments; + g_signal_emit_by_name (self, "changed"); + result = TRUE; + return result; } -void -page_view_button_press (PageView *view, gint x, gint y) -{ - CropLocation location; - - g_return_if_fail (view != NULL); - - /* See if selecting crop */ - location = get_crop_location (view, x, y);; - if (location != CROP_NONE) { - view->priv->crop_location = location; - view->priv->selected_crop_px = x; - view->priv->selected_crop_py = y; - page_get_crop (view->priv->page, - &view->priv->selected_crop_x, - &view->priv->selected_crop_y, - &view->priv->selected_crop_w, - &view->priv->selected_crop_h); - } +static gboolean _page_view_animation_cb_gsource_func (gpointer self) { + gboolean result; + result = page_view_animation_cb (self); + return result; } -void -page_view_motion (PageView *view, gint x, gint y) -{ - gint pw, ph; - gint cx, cy, cw, ch, dx, dy; - gint new_x, new_y, new_w, new_h; - CropLocation location; - gint cursor; - gint min_size; - - min_size = screen_to_page_x (view, 15); - - g_return_if_fail (view != NULL); - - location = get_crop_location (view, x, y); - switch (location) { - case CROP_MIDDLE: - cursor = GDK_HAND1; - break; - case CROP_TOP: - cursor = GDK_TOP_SIDE; - break; - case CROP_BOTTOM: - cursor = GDK_BOTTOM_SIDE; - break; - case CROP_LEFT: - cursor = GDK_LEFT_SIDE; - break; - case CROP_RIGHT: - cursor = GDK_RIGHT_SIDE; - break; - case CROP_TOP_LEFT: - cursor = GDK_TOP_LEFT_CORNER; - break; - case CROP_TOP_RIGHT: - cursor = GDK_TOP_RIGHT_CORNER; - break; - case CROP_BOTTOM_LEFT: - cursor = GDK_BOTTOM_LEFT_CORNER; - break; - case CROP_BOTTOM_RIGHT: - cursor = GDK_BOTTOM_RIGHT_CORNER; - break; - default: - cursor = GDK_ARROW; - break; - } - - if (view->priv->crop_location == CROP_NONE) { - view->priv->cursor = cursor; - return; - } - - /* Move the crop */ - pw = page_get_width (view->priv->page); - ph = page_get_height (view->priv->page); - page_get_crop (view->priv->page, &cx, &cy, &cw, &ch); - - dx = screen_to_page_x (view, x - view->priv->selected_crop_px); - dy = screen_to_page_y (view, y - view->priv->selected_crop_py); - - new_x = view->priv->selected_crop_x; - new_y = view->priv->selected_crop_y; - new_w = view->priv->selected_crop_w; - new_h = view->priv->selected_crop_h; - - /* Limit motion to remain within page and minimum crop size */ - if (view->priv->crop_location == CROP_TOP_LEFT || - view->priv->crop_location == CROP_LEFT || - view->priv->crop_location == CROP_BOTTOM_LEFT) { - if (dx > new_w - min_size) - dx = new_w - min_size; - if (new_x + dx < 0) - dx = -new_x; - } - if (view->priv->crop_location == CROP_TOP_LEFT || - view->priv->crop_location == CROP_TOP || - view->priv->crop_location == CROP_TOP_RIGHT) { - if (dy > new_h - min_size) - dy = new_h - min_size; - if (new_y + dy < 0) - dy = -new_y; - } - - if (view->priv->crop_location == CROP_TOP_RIGHT || - view->priv->crop_location == CROP_RIGHT || - view->priv->crop_location == CROP_BOTTOM_RIGHT) { - if (dx < min_size - new_w) - dx = min_size - new_w; - if (new_x + new_w + dx > pw) - dx = pw - new_x - new_w; - } - if (view->priv->crop_location == CROP_BOTTOM_LEFT || - view->priv->crop_location == CROP_BOTTOM || - view->priv->crop_location == CROP_BOTTOM_RIGHT) { - if (dy < min_size - new_h) - dy = min_size - new_h; - if (new_y + new_h + dy > ph) - dy = ph - new_y - new_h; - } - if (view->priv->crop_location == CROP_MIDDLE) { - if (new_x + dx + new_w > pw) - dx = pw - new_x - new_w; - if (new_x + dx < 0) - dx = -new_x; - if (new_y + dy + new_h > ph) - dy = ph - new_y - new_h; - if (new_y + dy < 0) - dy = -new_y; - } - - /* Move crop */ - if (view->priv->crop_location == CROP_MIDDLE) { - new_x += dx; - new_y += dy; - } - if (view->priv->crop_location == CROP_TOP_LEFT || - view->priv->crop_location == CROP_LEFT || - view->priv->crop_location == CROP_BOTTOM_LEFT) - { - new_x += dx; - new_w -= dx; - } - if (view->priv->crop_location == CROP_TOP_LEFT || - view->priv->crop_location == CROP_TOP || - view->priv->crop_location == CROP_TOP_RIGHT) { - new_y += dy; - new_h -= dy; - } - - if (view->priv->crop_location == CROP_TOP_RIGHT || - view->priv->crop_location == CROP_RIGHT || - view->priv->crop_location == CROP_BOTTOM_RIGHT) { - new_w += dx; - } - if (view->priv->crop_location == CROP_BOTTOM_LEFT || - view->priv->crop_location == CROP_BOTTOM || - view->priv->crop_location == CROP_BOTTOM_RIGHT) { - new_h += dy; - } - - page_move_crop (view->priv->page, new_x, new_y); - - /* If reshaped crop, must be a custom crop */ - if (new_w != cw || new_h != ch) - page_set_custom_crop (view->priv->page, new_w, new_h); +static void page_view_update_animation (PageView* self) { + gboolean animate = FALSE; + gboolean is_animating = FALSE; + gboolean _tmp0_ = FALSE; + gboolean _tmp1_; + g_return_if_fail (self != NULL); + _tmp1_ = page_is_scanning (self->priv->page); + if (_tmp1_) { + gboolean _tmp2_; + _tmp2_ = page_has_data (self->priv->page); + _tmp0_ = !_tmp2_; + } else { + _tmp0_ = FALSE; + } + animate = _tmp0_; + is_animating = self->priv->animate_timeout != ((guint) 0); + if (animate == is_animating) { + return; + } + if (animate) { + self->priv->animate_segment = 0; + if (self->priv->animate_timeout == ((guint) 0)) { + guint _tmp3_; + _tmp3_ = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 150, _page_view_animation_cb_gsource_func, page_view_ref (self), page_view_unref); + self->priv->animate_timeout = _tmp3_; + } + } else { + if (self->priv->animate_timeout != ((guint) 0)) { + g_source_remove (self->priv->animate_timeout); + } + self->priv->animate_timeout = (guint) 0; + } } -void -page_view_button_release (PageView *view, gint x, gint y) -{ - g_return_if_fail (view != NULL); +void page_view_render (PageView* self, cairo_t* context) { + gint _tmp0_; + gint w; + gint _tmp1_; + gint h; + gboolean _tmp2_ = FALSE; + gboolean _tmp3_; + gboolean _tmp11_ = FALSE; + gboolean _tmp12_; + gboolean _tmp20_; + g_return_if_fail (self != NULL); + g_return_if_fail (context != NULL); + page_view_update_animation (self); + page_view_update_page_view (self); + _tmp0_ = page_view_get_preview_width (self); + w = _tmp0_; + _tmp1_ = page_view_get_preview_height (self); + h = _tmp1_; + cairo_set_line_width (context, (gdouble) 1); + cairo_translate (context, (gdouble) self->priv->x_offset, (gdouble) self->priv->y_offset); + cairo_set_source_rgb (context, (gdouble) 0, (gdouble) 0, (gdouble) 0); + cairo_set_line_width (context, (gdouble) self->priv->border_width); + cairo_rectangle (context, ((gdouble) self->priv->border_width) / 2, ((gdouble) self->priv->border_width) / 2, (gdouble) (self->priv->width - self->priv->border_width), (gdouble) (self->priv->height - self->priv->border_width)); + cairo_stroke (context); + cairo_translate (context, (gdouble) self->priv->border_width, (gdouble) self->priv->border_width); + gdk_cairo_set_source_pixbuf (context, self->priv->image, (gdouble) 0, (gdouble) 0); + cairo_paint (context); + _tmp3_ = page_is_scanning (self->priv->page); + if (_tmp3_) { + gboolean _tmp4_; + _tmp4_ = page_has_data (self->priv->page); + _tmp2_ = !_tmp4_; + } else { + _tmp2_ = FALSE; + } + if (_tmp2_) { + gdouble outer_radius = 0.0; + gdouble arc; + gdouble _tmp5_; + gdouble x; + gdouble _tmp6_; + gdouble y; + gdouble _tmp7_; + gdouble inner_radius; + gdouble offset; + if (w > h) { + outer_radius = 0.15 * w; + } else { + outer_radius = 0.15 * h; + } + arc = G_PI / self->priv->animate_n_segments; + _tmp5_ = sin (arc); + x = outer_radius * _tmp5_; + _tmp6_ = cos (arc); + y = outer_radius * (_tmp6_ - 1.0); + _tmp7_ = sqrt ((x * x) + (y * y)); + inner_radius = 0.6 * _tmp7_; + offset = 0.0; + { + gint i; + i = 0; + { + gboolean _tmp8_; + _tmp8_ = TRUE; + while (TRUE) { + gdouble _tmp9_; + gdouble _tmp10_; + if (!_tmp8_) { + i++; + offset = offset + (arc * 2); + } + _tmp8_ = FALSE; + if (!(i < self->priv->animate_n_segments)) { + break; + } + _tmp9_ = sin (offset); + x = (w / 2) + (outer_radius * _tmp9_); + _tmp10_ = cos (offset); + y = (h / 2) - (outer_radius * _tmp10_); + cairo_arc (context, x, y, inner_radius, (gdouble) 0, 2 * G_PI); + if (i == self->priv->animate_segment) { + cairo_set_source_rgb (context, 0.75, 0.75, 0.75); + cairo_fill_preserve (context); + } + cairo_set_source_rgb (context, 0.5, 0.5, 0.5); + cairo_stroke (context); + } + } + } + } + _tmp12_ = page_is_scanning (self->priv->page); + if (_tmp12_) { + gint _tmp13_; + _tmp13_ = page_get_scan_line (self->priv->page); + _tmp11_ = _tmp13_ > 0; + } else { + _tmp11_ = FALSE; + } + if (_tmp11_) { + gint _tmp14_; + gint scan_line; + gdouble s = 0.0; + gdouble x1 = 0.0; + gdouble y1 = 0.0; + gdouble x2 = 0.0; + gdouble y2 = 0.0; + ScanDirection _tmp15_; + _tmp14_ = page_get_scan_line (self->priv->page); + scan_line = _tmp14_; + _tmp15_ = page_get_scan_direction (self->priv->page); + switch (_tmp15_) { + case SCAN_DIRECTION_TOP_TO_BOTTOM: + { + gint _tmp16_; + _tmp16_ = page_view_page_to_screen_y (self, scan_line); + s = (gdouble) _tmp16_; + x1 = (gdouble) 0; + y1 = s + 0.5; + x2 = (gdouble) w; + y2 = s + 0.5; + break; + } + case SCAN_DIRECTION_BOTTOM_TO_TOP: + { + gint _tmp17_; + _tmp17_ = page_view_page_to_screen_y (self, scan_line); + s = (gdouble) _tmp17_; + x1 = (gdouble) 0; + y1 = (h - s) + 0.5; + x2 = (gdouble) w; + y2 = (h - s) + 0.5; + break; + } + case SCAN_DIRECTION_LEFT_TO_RIGHT: + { + gint _tmp18_; + _tmp18_ = page_view_page_to_screen_x (self, scan_line); + s = (gdouble) _tmp18_; + x1 = s + 0.5; + y1 = (gdouble) 0; + x2 = s + 0.5; + y2 = (gdouble) h; + break; + } + case SCAN_DIRECTION_RIGHT_TO_LEFT: + { + gint _tmp19_; + _tmp19_ = page_view_page_to_screen_x (self, scan_line); + s = (gdouble) _tmp19_; + x1 = (w - s) + 0.5; + y1 = (gdouble) 0; + x2 = (w - s) + 0.5; + y2 = (gdouble) h; + break; + } + default: + { + y2 = (gdouble) 0; + x2 = y2; + y1 = x2; + x1 = y1; + break; + } + } + cairo_move_to (context, x1, y1); + cairo_line_to (context, x2, y2); + cairo_set_source_rgb (context, 1.0, 0.0, 0.0); + cairo_stroke (context); + } + _tmp20_ = page_has_crop (self->priv->page); + if (_tmp20_) { + gint x = 0; + gint y = 0; + gint crop_width = 0; + gint crop_height = 0; + gint _tmp21_; + gint _tmp22_; + gint _tmp23_; + gint _tmp24_; + gint _tmp25_; + gint dx; + gint _tmp26_; + gint dy; + gint _tmp27_; + gint dw; + gint _tmp28_; + gint dh; + page_get_crop (self->priv->page, &_tmp21_, &_tmp22_, &_tmp23_, &_tmp24_); + x = _tmp21_; + y = _tmp22_; + crop_width = _tmp23_; + crop_height = _tmp24_; + _tmp25_ = page_view_page_to_screen_x (self, x); + dx = _tmp25_; + _tmp26_ = page_view_page_to_screen_y (self, y); + dy = _tmp26_; + _tmp27_ = page_view_page_to_screen_x (self, crop_width); + dw = _tmp27_; + _tmp28_ = page_view_page_to_screen_y (self, crop_height); + dh = _tmp28_; + cairo_rectangle (context, (gdouble) 0, (gdouble) 0, (gdouble) w, (gdouble) h); + cairo_new_sub_path (context); + cairo_rectangle (context, (gdouble) dx, (gdouble) dy, (gdouble) dw, (gdouble) dh); + cairo_set_fill_rule (context, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_source_rgba (context, 0.25, 0.25, 0.25, 0.2); + cairo_fill (context); + cairo_rectangle (context, dx - 1.5, dy - 1.5, (gdouble) (dw + 3), (gdouble) (dh + 3)); + cairo_set_source_rgb (context, 1.0, 1.0, 1.0); + cairo_stroke (context); + cairo_rectangle (context, dx - 0.5, dy - 0.5, (gdouble) (dw + 1), (gdouble) (dh + 1)); + cairo_set_source_rgb (context, 0.0, 0.0, 0.0); + cairo_stroke (context); + } +} + - /* Complete crop */ - view->priv->crop_location = CROP_NONE; - g_signal_emit (view, signals[CHANGED], 0); +void page_view_set_width (PageView* self, gint width) { + gint _tmp0_; + gint _tmp1_; + gint height; + gboolean _tmp2_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = page_get_height (self->priv->page); + _tmp1_ = page_get_width (self->priv->page); + height = (gint) ((((gdouble) width) * _tmp0_) / _tmp1_); + if (self->priv->width == width) { + _tmp2_ = self->priv->height == height; + } else { + _tmp2_ = FALSE; + } + if (_tmp2_) { + return; + } + self->priv->width = width; + self->priv->height = height; + self->priv->update_image = TRUE; + g_signal_emit_by_name (self, "size-changed"); + g_signal_emit_by_name (self, "changed"); } -gint -page_view_get_cursor (PageView *view) -{ - g_return_val_if_fail (view != NULL, 0); - return view->priv->cursor; +void page_view_set_height (PageView* self, gint height) { + gint _tmp0_; + gint _tmp1_; + gint width; + gboolean _tmp2_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = page_get_width (self->priv->page); + _tmp1_ = page_get_height (self->priv->page); + width = (gint) ((((gdouble) height) * _tmp0_) / _tmp1_); + if (self->priv->width == width) { + _tmp2_ = self->priv->height == height; + } else { + _tmp2_ = FALSE; + } + if (_tmp2_) { + return; + } + self->priv->width = width; + self->priv->height = height; + self->priv->update_image = TRUE; + g_signal_emit_by_name (self, "size-changed"); + g_signal_emit_by_name (self, "changed"); } -static gboolean -animation_cb (PageView *view) -{ - view->priv->animate_segment = (view->priv->animate_segment + 1) % view->priv->animate_n_segments; - g_signal_emit (view, signals[CHANGED], 0); - return TRUE; +gint page_view_get_width (PageView* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->width; + return result; } -static void -update_animation (PageView *view) -{ - gboolean animate, is_animating; - - animate = page_is_scanning (view->priv->page) && !page_has_data (view->priv->page); - is_animating = view->priv->animate_timeout != 0; - if (animate == is_animating) - return; - - if (animate) { - view->priv->animate_segment = 0; - if (view->priv->animate_timeout == 0) - view->priv->animate_timeout = g_timeout_add (150, (GSourceFunc) animation_cb, view); - } - else - { - if (view->priv->animate_timeout != 0) - g_source_remove (view->priv->animate_timeout); - view->priv->animate_timeout = 0; - } +gint page_view_get_height (PageView* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->height; + return result; } -void -page_view_render (PageView *view, cairo_t *context) -{ - gint width, height; - - g_return_if_fail (view != NULL); - g_return_if_fail (context != NULL); - - update_animation (view); - update_page_view (view); - - width = get_preview_width (view); - height = get_preview_height (view); - - cairo_set_line_width (context, 1); - cairo_translate (context, view->priv->x, view->priv->y); - - /* Draw page border */ - cairo_set_source_rgb (context, 0, 0, 0); - cairo_set_line_width (context, view->priv->border_width); - cairo_rectangle (context, - (double)view->priv->border_width / 2, - (double)view->priv->border_width / 2, - view->priv->width - view->priv->border_width, - view->priv->height - view->priv->border_width); - cairo_stroke (context); - - /* Draw image */ - cairo_translate (context, view->priv->border_width, view->priv->border_width); - gdk_cairo_set_source_pixbuf (context, view->priv->image, 0, 0); - cairo_paint (context); - - /* Draw throbber */ - if (page_is_scanning (view->priv->page) && !page_has_data (view->priv->page)) { - gdouble inner_radius, outer_radius, x, y, arc, offset = 0.0; - gint i; - - if (width > height) - outer_radius = 0.15 * width; - else - outer_radius = 0.15 * height; - arc = M_PI / view->priv->animate_n_segments; - - /* Space circles */ - x = outer_radius * sin (arc); - y = outer_radius * (cos (arc) - 1.0); - inner_radius = 0.6 * sqrt (x*x + y*y); - - for (i = 0; i < view->priv->animate_n_segments; i++, offset += arc * 2) { - x = width / 2 + outer_radius * sin (offset); - y = height / 2 - outer_radius * cos (offset); - cairo_arc (context, x, y, inner_radius, 0, 2 * M_PI); - - if (i == view->priv->animate_segment) { - cairo_set_source_rgb (context, 0.75, 0.75, 0.75); - cairo_fill_preserve (context); - } - - cairo_set_source_rgb (context, 0.5, 0.5, 0.5); - cairo_stroke (context); - } - } - - /* Draw scan line */ - if (page_is_scanning (view->priv->page) && page_get_scan_line (view->priv->page) > 0) { - gint scan_line; - double s; - double x1, y1, x2, y2; - - scan_line = page_get_scan_line (view->priv->page); - - switch (page_get_scan_direction (view->priv->page)) { - case TOP_TO_BOTTOM: - s = page_to_screen_y (view, scan_line); - x1 = 0; y1 = s + 0.5; - x2 = width; y2 = s + 0.5; - break; - case BOTTOM_TO_TOP: - s = page_to_screen_y (view, scan_line); - x1 = 0; y1 = height - s + 0.5; - x2 = width; y2 = height - s + 0.5; - break; - case LEFT_TO_RIGHT: - s = page_to_screen_x (view, scan_line); - x1 = s + 0.5; y1 = 0; - x2 = s + 0.5; y2 = height; - break; - case RIGHT_TO_LEFT: - s = page_to_screen_x (view, scan_line); - x1 = width - s + 0.5; y1 = 0; - x2 = width - s + 0.5; y2 = height; - break; - default: - x1 = y1 = x2 = y2 = 0; - break; - } - - cairo_move_to (context, x1, y1); - cairo_line_to (context, x2, y2); - cairo_set_source_rgb (context, 1.0, 0.0, 0.0); - cairo_stroke (context); - } - - /* Draw crop */ - if (page_has_crop (view->priv->page)) { - gint x, y, crop_width, crop_height; - gdouble dx, dy, dw, dh; - - page_get_crop (view->priv->page, &x, &y, &crop_width, &crop_height); - - dx = page_to_screen_x (view, x); - dy = page_to_screen_y (view, y); - dw = page_to_screen_x (view, crop_width); - dh = page_to_screen_y (view, crop_height); - - /* Shade out cropped area */ - cairo_rectangle (context, - 0, 0, - width, height); - cairo_new_sub_path (context); - cairo_rectangle (context, dx, dy, dw, dh); - cairo_set_fill_rule (context, CAIRO_FILL_RULE_EVEN_ODD); - cairo_set_source_rgba (context, 0.25, 0.25, 0.25, 0.2); - cairo_fill (context); - - /* Show new edge */ - cairo_rectangle (context, dx - 1.5, dy - 1.5, dw + 3, dh + 3); - cairo_set_source_rgb (context, 1.0, 1.0, 1.0); - cairo_stroke (context); - cairo_rectangle (context, dx - 0.5, dy - 0.5, dw + 1, dh + 1); - cairo_set_source_rgb (context, 0.0, 0.0, 0.0); - cairo_stroke (context); - } +static void page_view_page_pixels_changed_cb (PageView* self, Page* p) { + g_return_if_fail (self != NULL); + g_return_if_fail (p != NULL); + self->priv->update_image = TRUE; + g_signal_emit_by_name (self, "changed"); } -void -page_view_set_width (PageView *view, gint width) -{ - gint height; +static void page_view_page_size_changed_cb (PageView* self, Page* p) { + g_return_if_fail (self != NULL); + g_return_if_fail (p != NULL); + self->priv->update_image = TRUE; + g_signal_emit_by_name (self, "size-changed"); + g_signal_emit_by_name (self, "changed"); +} - g_return_if_fail (view != NULL); - // FIXME: Automatically update when get updated image - height = (double)width * page_get_height (view->priv->page) / page_get_width (view->priv->page); - if (view->priv->width == width && view->priv->height == height) - return; +static void page_view_page_overlay_changed_cb (PageView* self, Page* p) { + g_return_if_fail (self != NULL); + g_return_if_fail (p != NULL); + g_signal_emit_by_name (self, "changed"); +} - view->priv->width = width; - view->priv->height = height; - - /* Regenerate image */ - view->priv->update_image = TRUE; - g_signal_emit (view, signals[SIZE_CHANGED], 0); - g_signal_emit (view, signals[CHANGED], 0); +static void page_view_scan_direction_changed_cb (PageView* self, Page* p) { + g_return_if_fail (self != NULL); + g_return_if_fail (p != NULL); + self->priv->update_image = TRUE; + g_signal_emit_by_name (self, "size-changed"); + g_signal_emit_by_name (self, "changed"); } -void -page_view_set_height (PageView *view, gint height) -{ - gint width; +static void value_page_view_init (GValue* value) { + value->data[0].v_pointer = NULL; +} - g_return_if_fail (view != NULL); - // FIXME: Automatically update when get updated image - width = (double)height * page_get_width (view->priv->page) / page_get_height (view->priv->page); - if (view->priv->width == width && view->priv->height == height) - return; +static void value_page_view_free_value (GValue* value) { + if (value->data[0].v_pointer) { + page_view_unref (value->data[0].v_pointer); + } +} - view->priv->width = width; - view->priv->height = height; - - /* Regenerate image */ - view->priv->update_image = TRUE; - g_signal_emit (view, signals[SIZE_CHANGED], 0); - g_signal_emit (view, signals[CHANGED], 0); +static void value_page_view_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = page_view_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } } -gint -page_view_get_width (PageView *view) -{ - g_return_val_if_fail (view != NULL, 0); - return view->priv->width; +static gpointer value_page_view_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; } -gint -page_view_get_height (PageView *view) -{ - g_return_val_if_fail (view != NULL, 0); - return view->priv->height; +static gchar* value_page_view_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + PageView* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = page_view_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; } -static void -page_pixels_changed_cb (Page *p, PageView *view) -{ - /* Regenerate image */ - view->priv->update_image = TRUE; - g_signal_emit (view, signals[CHANGED], 0); +static gchar* value_page_view_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + PageView** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = page_view_ref (value->data[0].v_pointer); + } + return NULL; } -static void -page_size_changed_cb (Page *p, PageView *view) -{ - /* Regenerate image */ - view->priv->update_image = TRUE; - g_signal_emit (view, signals[SIZE_CHANGED], 0); - g_signal_emit (view, signals[CHANGED], 0); +GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPageView* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PAGE_VIEW), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); } -static void -page_overlay_changed_cb (Page *p, PageView *view) -{ - g_signal_emit (view, signals[CHANGED], 0); +gpointer value_get_page_view (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW), NULL); + return value->data[0].v_pointer; } -static void -scan_direction_changed_cb (Page *p, PageView *view) -{ - /* Regenerate image */ - view->priv->update_image = TRUE; - g_signal_emit (view, signals[SIZE_CHANGED], 0); - g_signal_emit (view, signals[CHANGED], 0); +void value_set_page_view (GValue* value, gpointer v_object) { + PageView* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE_VIEW)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + page_view_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + page_view_unref (old); + } } -static void -page_view_set_page (PageView *view, Page *page) -{ - g_return_if_fail (view != NULL); - g_return_if_fail (view->priv->page == NULL); +void value_take_page_view (GValue* value, gpointer v_object) { + PageView* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE_VIEW)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + page_view_unref (old); + } +} + - view->priv->page = g_object_ref (page); - g_signal_connect (view->priv->page, "pixels-changed", G_CALLBACK (page_pixels_changed_cb), view); - g_signal_connect (view->priv->page, "size-changed", G_CALLBACK (page_size_changed_cb), view); - g_signal_connect (view->priv->page, "crop-changed", G_CALLBACK (page_overlay_changed_cb), view); - g_signal_connect (view->priv->page, "scan-line-changed", G_CALLBACK (page_overlay_changed_cb), view); - g_signal_connect (view->priv->page, "scan-direction-changed", G_CALLBACK (scan_direction_changed_cb), view); +static void page_view_class_init (PageViewClass * klass) { + page_view_parent_class = g_type_class_peek_parent (klass); + PAGE_VIEW_CLASS (klass)->finalize = page_view_finalize; + g_type_class_add_private (klass, sizeof (PageViewPrivate)); + g_signal_new ("size_changed", TYPE_PAGE_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("changed", TYPE_PAGE_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } -static void -page_view_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PageView *self; - - self = PAGE_VIEW (object); - - switch (prop_id) { - case PROP_PAGE: - page_view_set_page (self, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +static void page_view_instance_init (PageView * self) { + self->priv = PAGE_VIEW_GET_PRIVATE (self); + self->priv->image = NULL; + self->priv->border_width = 1; + self->priv->update_image = TRUE; + self->priv->cursor = GDK_ARROW; + self->priv->animate_n_segments = 7; + self->ref_count = 1; } -static void -page_view_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PageView *self; - - self = PAGE_VIEW (object); - - switch (prop_id) { - case PROP_PAGE: - g_value_set_object (value, self->priv->page); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +static void page_view_finalize (PageView* obj) { + PageView * self; + self = PAGE_VIEW (obj); + _page_unref0 (self->priv->page); + _g_object_unref0 (self->priv->image); } -static void -page_view_finalize (GObject *object) -{ - PageView *view = PAGE_VIEW (object); - g_object_unref (view->priv->page); - view->priv->page = NULL; - if (view->priv->image) - g_object_unref (view->priv->image); - view->priv->image = NULL; - if (view->priv->animate_timeout != 0) - g_source_remove (view->priv->animate_timeout); - view->priv->animate_timeout = 0; - G_OBJECT_CLASS (page_view_parent_class)->finalize (object); +GType page_view_get_type (void) { + static volatile gsize page_view_type_id__volatile = 0; + if (g_once_init_enter (&page_view_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_page_view_init, value_page_view_free_value, value_page_view_copy_value, value_page_view_peek_pointer, "p", value_page_view_collect_value, "p", value_page_view_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PageViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) page_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PageView), 0, (GInstanceInitFunc) page_view_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType page_view_type_id; + page_view_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PageView", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&page_view_type_id__volatile, page_view_type_id); + } + return page_view_type_id__volatile; } -static void -page_view_class_init (PageViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = page_view_get_property; - object_class->set_property = page_view_set_property; - object_class->finalize = page_view_finalize; - - signals[CHANGED] = - g_signal_new ("changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageViewClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[SIZE_CHANGED] = - g_signal_new ("size-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageViewClass, size_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (PageViewPrivate)); - - g_object_class_install_property (object_class, - PROP_PAGE, - g_param_spec_object ("page", - "page", - "Page being rendered", - PAGE_TYPE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +gpointer page_view_ref (gpointer instance) { + PageView* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -static void -page_view_init (PageView *view) -{ - view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, PAGE_VIEW_TYPE, PageViewPrivate); - view->priv->update_image = TRUE; - view->priv->cursor = GDK_ARROW; - view->priv->border_width = 1; - view->priv->animate_n_segments = 7; +void page_view_unref (gpointer instance) { + PageView* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PAGE_VIEW_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } } + + + diff --git a/src/page-view.h b/src/page-view.h deleted file mode 100644 index dd64197..0000000 --- a/src/page-view.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2009 Canonical Ltd. - * Author: Robert Ancell <robert.ancell@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. See http://www.gnu.org/copyleft/gpl.html the full text of the - * license. - */ - -#ifndef _PAGE_VIEW_H_ -#define _PAGE_VIEW_H_ - -#include <glib-object.h> -#include <gtk/gtk.h> -#include <cairo.h> -#include "page.h" - -G_BEGIN_DECLS - -#define PAGE_VIEW_TYPE (page_view_get_type ()) -#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PAGE_VIEW_TYPE, PageView)) - - -typedef struct PageViewPrivate PageViewPrivate; - -typedef struct -{ - GObject parent_instance; - PageViewPrivate *priv; -} PageView; - -typedef struct -{ - GObjectClass parent_class; - - void (*changed) (PageView *view); - void (*size_changed) (PageView *view); -} PageViewClass; - - -GType page_view_get_type (void); - -PageView *page_view_new (Page *page); - -Page *page_view_get_page (PageView *view); - -void page_view_set_selected (PageView *view, gboolean selected); - -gboolean page_view_get_selected (PageView *view); - -void page_view_set_x_offset (PageView *view, gint offset); - -void page_view_set_y_offset (PageView *view, gint offset); - -gint page_view_get_x_offset (PageView *view); - -gint page_view_get_y_offset (PageView *view); - -void page_view_set_width (PageView *view, gint width); - -void page_view_set_height (PageView *view, gint height); - -gint page_view_get_width (PageView *view); - -gint page_view_get_height (PageView *view); - -void page_view_button_press (PageView *view, gint x, gint y); - -void page_view_motion (PageView *view, gint x, gint y); - -void page_view_button_release (PageView *view, gint x, gint y); - -gint page_view_get_cursor (PageView *view); - -void page_view_render (PageView *view, cairo_t *context); - -#endif /* _PAGE_VIEW_H_ */ diff --git a/src/page-view.vala b/src/page-view.vala new file mode 100644 index 0000000..97bcaf0 --- /dev/null +++ b/src/page-view.vala @@ -0,0 +1,1043 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public enum CropLocation +{ + NONE = 0, + MIDDLE, + TOP, + BOTTOM, + LEFT, + RIGHT, + TOP_LEFT, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_RIGHT +} + +public class PageView +{ + /* Page being rendered */ + private Page page; + + /* Image to render at current resolution */ + private Gdk.Pixbuf? image = null; + + /* Border around image */ + private bool selected; + private int border_width = 1; + + /* True if image needs to be regenerated */ + private bool update_image = true; + + /* Direction of currently scanned image */ + private ScanDirection scan_direction; + + /* Next scan line to render */ + private int scan_line; + + /* Dimensions of image to generate */ + private int width; + private int height; + + /* Location to place this page */ + private int x_offset; + private int y_offset; + + private CropLocation crop_location; + private double selected_crop_px; + private double selected_crop_py; + private int selected_crop_x; + private int selected_crop_y; + private int selected_crop_w; + private int selected_crop_h; + + /* Cursor over this page */ + private Gdk.CursorType cursor = Gdk.CursorType.ARROW; + + private int animate_n_segments = 7; + private int animate_segment; + private uint animate_timeout; + + public signal void size_changed (); + public signal void changed (); + + public PageView (Page page) + { + this.page = page; + page.pixels_changed.connect (page_pixels_changed_cb); + page.size_changed.connect (page_size_changed_cb); + page.crop_changed.connect (page_overlay_changed_cb); + page.scan_line_changed.connect (page_overlay_changed_cb); + page.scan_direction_changed.connect (scan_direction_changed_cb); + } + + public Page get_page () + { + return page; + } + + public void set_selected (bool selected) + { + if ((this.selected && selected) || (!this.selected && !selected)) + return; + this.selected = selected; + changed (); + } + + public bool get_selected () + { + return selected; + } + + public void set_x_offset (int offset) + { + x_offset = offset; + } + + public void set_y_offset (int offset) + { + y_offset = offset; + } + + public int get_x_offset () + { + return x_offset; + } + + public int get_y_offset () + { + return y_offset; + } + + private uchar get_sample (uchar[] pixels, int offset, int x, int depth, int sample) + { + // FIXME + return 0xFF; + } + + private void get_pixel (Page page, int x, int y, uchar[] pixel) + { + switch (page.get_scan_direction ()) + { + case ScanDirection.TOP_TO_BOTTOM: + break; + case ScanDirection.BOTTOM_TO_TOP: + x = page.get_scan_width () - x - 1; + y = page.get_scan_height () - y - 1; + break; + case ScanDirection.LEFT_TO_RIGHT: + var t = x; + x = page.get_scan_width () - y - 1; + y = t; + break; + case ScanDirection.RIGHT_TO_LEFT: + var t = x; + x = y; + y = page.get_scan_height () - t - 1; + break; + } + + var depth = page.get_depth (); + var n_channels = page.get_n_channels (); + unowned uchar[] pixels = page.get_pixels (); + var offset = page.get_rowstride () * y; + + /* Optimise for 8 bit images */ + if (depth == 8 && n_channels == 3) + { + var o = offset + x * n_channels; + pixel[0] = pixels[o]; + pixel[1] = pixels[o+1]; + pixel[2] = pixels[o+2]; + return; + } + else if (depth == 8 && n_channels == 1) + { + pixel[0] = pixel[1] = pixel[2] = pixels[offset + x]; + return; + } + + /* Optimise for bitmaps */ + else if (depth == 1 && n_channels == 1) + { + var o = offset + (x / 8); + pixel[0] = pixel[1] = pixel[2] = (pixels[o] & (0x80 >> (x % 8))) != 0 ? 0x00 : 0xFF; + return; + } + + /* Optimise for 2 bit images */ + else if (depth == 2 && n_channels == 1) + { + int block_shift[4] = { 6, 4, 2, 0 }; + + var o = offset + (x / 4); + var sample = (pixels[o] >> block_shift[x % 4]) & 0x3; + sample = sample * 255 / 3; + + pixel[0] = pixel[1] = pixel[2] = (uchar) sample; + return; + } + + /* Use slow method */ + pixel[0] = get_sample (pixels, offset, x, depth, x * n_channels); + pixel[1] = get_sample (pixels, offset, x, depth, x * n_channels + 1); + pixel[2] = get_sample (pixels, offset, x, depth, x * n_channels + 2); + } + + private void set_pixel (Page page, double l, double r, double t, double b, uchar[] output, int offset) + { + /* Decimation: + * + * Target pixel is defined by (t,l)-(b,r) + * It touches 16 pixels in original image + * It completely covers 4 pixels in original image (T,L)-(B,R) + * Add covered pixels and add weighted partially covered pixels. + * Divide by total area. + * + * l L R r + * +-----+-----+-----+-----+ + * | | | | | + * t | +--+-----+-----+---+ | + * T +--+--+-----+-----+---+-+ + * | | | | | | | + * | | | | | | | + * +--+--+-----+-----+---+-+ + * | | | | | | | + * | | | | | | | + * B +--+--+-----+-----+---+-+ + * | | | | | | | + * b | +--+-----+-----+---+ | + * +-----+-----+-----+-----+ + * + * + * Interpolation: + * + * l r + * +-----+-----+-----+-----+ + * | | | | | + * | | | | | + * +-----+-----+-----+-----+ + * t | | +-+--+ | | + * | | | | | | | + * +-----+---+-+--+--+-----+ + * b | | +-+--+ | | + * | | | | | + * +-----+-----+-----+-----+ + * | | | | | + * | | | | | + * +-----+-----+-----+-----+ + * + * Same again, just no completely covered pixels. + */ + + var L = (int) l; + if (L != l) + L++; + var R = (int) r; + var T = (int) t; + if (T != t) + T++; + var B = (int) b; + + var red = 0.0; + var green = 0.0; + var blue = 0.0; + + /* Target can fit inside one source pixel + * +-----+ + * | | + * | +--+| +-----+-----+ +-----+ +-----+ +-----+ + * +-+--++ or | +-++ | or | +-+ | or | +--+| or | +--+ + * | +--+| | +-++ | | +-+ | | | || | | | + * | | +-----+-----+ +-----+ +-+--++ +--+--+ + * +-----+ + */ + if ((r - l <= 1.0 && (int)r == (int)l) || (b - t <= 1.0 && (int)b == (int)t)) + { + /* Inside */ + if ((int)l == (int)r || (int)t == (int)b) + { + uchar p[3]; + get_pixel (page, (int)l, (int)t, p); + output[offset] = p[0]; + output[offset+1] = p[1]; + output[offset+2] = p[2]; + return; + } + + /* Stradling horizontal edge */ + if (L > R) + { + uchar p[3]; + get_pixel (page, R, T-1, p); + red += p[0] * (r-l)*(T-t); + green += p[1] * (r-l)*(T-t); + blue += p[2] * (r-l)*(T-t); + for (var y = T; y < B; y++) + { + get_pixel (page, R, y, p); + red += p[0] * (r-l); + green += p[1] * (r-l); + blue += p[2] * (r-l); + } + get_pixel (page, R, B, p); + red += p[0] * (r-l)*(b-B); + green += p[1] * (r-l)*(b-B); + blue += p[2] * (r-l)*(b-B); + } + /* Stradling vertical edge */ + else + { + uchar p[3]; + get_pixel (page, L - 1, B, p); + red += p[0] * (b-t)*(L-l); + green += p[1] * (b-t)*(L-l); + blue += p[2] * (b-t)*(L-l); + for (var x = L; x < R; x++) { + get_pixel (page, x, B, p); + red += p[0] * (b-t); + green += p[1] * (b-t); + blue += p[2] * (b-t); + } + get_pixel (page, R, B, p); + red += p[0] * (b-t)*(r-R); + green += p[1] * (b-t)*(r-R); + blue += p[2] * (b-t)*(r-R); + } + + var scale = 1.0 / ((r - l) * (b - t)); + output[offset] = (uchar)(red * scale + 0.5); + output[offset+1] = (uchar)(green * scale + 0.5); + output[offset+2] = (uchar)(blue * scale + 0.5); + return; + } + + /* Add the middle pixels */ + for (var x = L; x < R; x++) + { + for (var y = T; y < B; y++) + { + uchar p[3]; + get_pixel (page, x, y, p); + red += p[0]; + green += p[1]; + blue += p[2]; + } + } + + /* Add the weighted top and bottom pixels */ + for (var x = L; x < R; x++) + { + if (t != T) + { + uchar p[3]; + get_pixel (page, x, T - 1, p); + red += p[0] * (T - t); + green += p[1] * (T - t); + blue += p[2] * (T - t); + } + + if (b != B) + { + uchar p[3]; + get_pixel (page, x, B, p); + red += p[0] * (b - B); + green += p[1] * (b - B); + blue += p[2] * (b - B); + } + } + + /* Add the left and right pixels */ + for (var y = T; y < B; y++) + { + if (l != L) + { + uchar p[3]; + get_pixel (page, L - 1, y, p); + red += p[0] * (L - l); + green += p[1] * (L - l); + blue += p[2] * (L - l); + } + + if (r != R) + { + uchar p[3]; + get_pixel (page, R, y, p); + red += p[0] * (r - R); + green += p[1] * (r - R); + blue += p[2] * (r - R); + } + } + + /* Add the corner pixels */ + if (l != L && t != T) + { + uchar p[3]; + get_pixel (page, L - 1, T - 1, p); + red += p[0] * (L - l)*(T - t); + green += p[1] * (L - l)*(T - t); + blue += p[2] * (L - l)*(T - t); + } + if (r != R && t != T) + { + uchar p[3]; + get_pixel (page, R, T - 1, p); + red += p[0] * (r - R)*(T - t); + green += p[1] * (r - R)*(T - t); + blue += p[2] * (r - R)*(T - t); + } + if (r != R && b != B) + { + uchar p[3]; + get_pixel (page, R, B, p); + red += p[0] * (r - R)*(b - B); + green += p[1] * (r - R)*(b - B); + blue += p[2] * (r - R)*(b - B); + } + if (l != L && b != B) + { + uchar p[3]; + get_pixel (page, L - 1, B, p); + red += p[0] * (L - l)*(b - B); + green += p[1] * (L - l)*(b - B); + blue += p[2] * (L - l)*(b - B); + } + + /* Scale pixel values and clamp in range [0, 255] */ + var scale = 1.0 / ((r - l) * (b - t)); + output[offset] = (uchar)(red * scale + 0.5); + output[offset+1] = (uchar)(green * scale + 0.5); + output[offset+2] = (uchar)(blue * scale + 0.5); + } + + private void update_preview (Page page, ref Gdk.Pixbuf? output_image, int output_width, int output_height, + ScanDirection scan_direction, int old_scan_line, int scan_line) + { + var input_width = page.get_width (); + var input_height = page.get_height (); + + /* Create new image if one does not exist or has changed size */ + int L, R, T, B; + if (output_image == null || + output_image.get_width () != output_width || + output_image.get_height () != output_height) + { + output_image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, + false, + 8, + output_width, + output_height); + + /* Update entire image */ + L = 0; + R = output_width - 1; + T = 0; + B = output_height - 1; + } + /* Otherwise only update changed area */ + else + { + switch (scan_direction) + { + case ScanDirection.TOP_TO_BOTTOM: + L = 0; + R = output_width - 1; + T = (int)((double)old_scan_line * output_height / input_height); + B = (int)((double)scan_line * output_height / input_height + 0.5); + break; + case ScanDirection.LEFT_TO_RIGHT: + L = (int)((double)old_scan_line * output_width / input_width); + R = (int)((double)scan_line * output_width / input_width + 0.5); + T = 0; + B = output_height - 1; + break; + case ScanDirection.BOTTOM_TO_TOP: + L = 0; + R = output_width - 1; + T = (int)((double)(input_height - scan_line) * output_height / input_height); + B = (int)((double)(input_height - old_scan_line) * output_height / input_height + 0.5); + break; + case ScanDirection.RIGHT_TO_LEFT: + L = (int)((double)(input_width - scan_line) * output_width / input_width); + R = (int)((double)(input_width - old_scan_line) * output_width / input_width + 0.5); + T = 0; + B = output_height - 1; + break; + default: + L = R = B = T = 0; + break; + } + } + + /* FIXME: There's an off by one error in there somewhere... */ + if (R >= output_width) + R = output_width - 1; + if (B >= output_height) + B = output_height - 1; + + return_if_fail (L >= 0); + return_if_fail (R < output_width); + return_if_fail (T >= 0); + return_if_fail (B < output_height); + return_if_fail (output_image != null); + + unowned uchar[] output = output_image.get_pixels (); + var output_rowstride = output_image.get_rowstride (); + var output_n_channels = output_image.get_n_channels (); + + if (!page.has_data ()) + { + for (var x = L; x <= R; x++) + for (var y = T; y <= B; y++) + { + var o = output_rowstride * y + x * output_n_channels; + output[o] = output[o+1] = output[o+2] = 0xFF; + } + return; + } + + /* Update changed area */ + for (var x = L; x <= R; x++) + { + var l = (double)x * input_width / output_width; + var r = (double)(x + 1) * input_width / output_width; + + for (var y = T; y <= B; y++) + { + var t = (double)y * input_height / output_height; + var b = (double)(y + 1) * input_height / output_height; + + set_pixel (page, + l, r, t, b, + output, output_rowstride * y + x * output_n_channels); + } + } + } + + private int get_preview_width () + { + return width - border_width * 2; + } + + private int get_preview_height () + { + return height - border_width * 2; + } + + private void update_page_view () + { + if (!update_image) + return; + + var old_scan_line = scan_line; + var scan_line = page.get_scan_line (); + + /* Delete old image if scan direction changed */ + var left_steps = scan_direction - page.get_scan_direction (); + if (left_steps != 0 && image != null) + image = null; + scan_direction = page.get_scan_direction (); + + update_preview (page, + ref image, + get_preview_width (), + get_preview_height (), + page.get_scan_direction (), old_scan_line, scan_line); + + update_image = false; + this.scan_line = scan_line; + } + + private int page_to_screen_x (int x) + { + return (int) ((double)x * get_preview_width () / page.get_width () + 0.5); + } + + private int page_to_screen_y (int y) + { + return (int) ((double)y * get_preview_height () / page.get_height () + 0.5); + } + + private int screen_to_page_x (int x) + { + return (int) ((double)x * page.get_width () / get_preview_width () + 0.5); + } + + private int screen_to_page_y (int y) + { + return (int) ((double)y * page.get_height () / get_preview_height () + 0.5); + } + + private CropLocation get_crop_location (int x, int y) + { + if (!page.has_crop ()) + return 0; + + int cx, cy, cw, ch; + page.get_crop (out cx, out cy, out cw, out ch); + var dx = page_to_screen_x (cx); + var dy = page_to_screen_y (cy); + var dw = page_to_screen_x (cw); + var dh = page_to_screen_y (ch); + var ix = x - dx; + var iy = y - dy; + + if (ix < 0 || ix > dw || iy < 0 || iy > dh) + return CropLocation.NONE; + + /* Can't resize named crops */ + var name = page.get_named_crop (); + if (name != null) + return CropLocation.MIDDLE; + + /* Adjust borders so can select */ + int crop_border = 20; + if (dw < crop_border * 3) + crop_border = dw / 3; + if (dh < crop_border * 3) + crop_border = dh / 3; + + /* Top left */ + if (ix < crop_border && iy < crop_border) + return CropLocation.TOP_LEFT; + /* Top right */ + if (ix > dw - crop_border && iy < crop_border) + return CropLocation.TOP_RIGHT; + /* Bottom left */ + if (ix < crop_border && iy > dh - crop_border) + return CropLocation.BOTTOM_LEFT; + /* Bottom right */ + if (ix > dw - crop_border && iy > dh - crop_border) + return CropLocation.BOTTOM_RIGHT; + + /* Left */ + if (ix < crop_border) + return CropLocation.LEFT; + /* Right */ + if (ix > dw - crop_border) + return CropLocation.RIGHT; + /* Top */ + if (iy < crop_border) + return CropLocation.TOP; + /* Bottom */ + if (iy > dh - crop_border) + return CropLocation.BOTTOM; + + /* In the middle */ + return CropLocation.MIDDLE; + } + + public void button_press (int x, int y) + { + CropLocation location; + + /* See if selecting crop */ + location = get_crop_location (x, y);; + if (location != CropLocation.NONE) + { + crop_location = location; + selected_crop_px = x; + selected_crop_py = y; + page.get_crop (out selected_crop_x, + out selected_crop_y, + out selected_crop_w, + out selected_crop_h); + } + } + + public void motion (int x, int y) + { + var location = get_crop_location (x, y); + Gdk.CursorType cursor; + switch (location) + { + case CropLocation.MIDDLE: + cursor = Gdk.CursorType.HAND1; + break; + case CropLocation.TOP: + cursor = Gdk.CursorType.TOP_SIDE; + break; + case CropLocation.BOTTOM: + cursor = Gdk.CursorType.BOTTOM_SIDE; + break; + case CropLocation.LEFT: + cursor = Gdk.CursorType.LEFT_SIDE; + break; + case CropLocation.RIGHT: + cursor = Gdk.CursorType.RIGHT_SIDE; + break; + case CropLocation.TOP_LEFT: + cursor = Gdk.CursorType.TOP_LEFT_CORNER; + break; + case CropLocation.TOP_RIGHT: + cursor = Gdk.CursorType.TOP_RIGHT_CORNER; + break; + case CropLocation.BOTTOM_LEFT: + cursor = Gdk.CursorType.BOTTOM_LEFT_CORNER; + break; + case CropLocation.BOTTOM_RIGHT: + cursor = Gdk.CursorType.BOTTOM_RIGHT_CORNER; + break; + default: + cursor = Gdk.CursorType.ARROW; + break; + } + + if (crop_location == CropLocation.NONE) + { + this.cursor = cursor; + return; + } + + /* Move the crop */ + var pw = page.get_width (); + var ph = page.get_height (); + int cx, cy, cw, ch; + page.get_crop (out cx, out cy, out cw, out ch); + + var dx = screen_to_page_x (x - (int) selected_crop_px); + var dy = screen_to_page_y (y - (int) selected_crop_py); + + var new_x = selected_crop_x; + var new_y = selected_crop_y; + var new_w = selected_crop_w; + var new_h = selected_crop_h; + + /* Limit motion to remain within page and minimum crop size */ + var min_size = screen_to_page_x (15); + if (crop_location == CropLocation.TOP_LEFT || + crop_location == CropLocation.LEFT || + crop_location == CropLocation.BOTTOM_LEFT) + { + if (dx > new_w - min_size) + dx = new_w - min_size; + if (new_x + dx < 0) + dx = -new_x; + } + if (crop_location == CropLocation.TOP_LEFT || + crop_location == CropLocation.TOP || + crop_location == CropLocation.TOP_RIGHT) + { + if (dy > new_h - min_size) + dy = new_h - min_size; + if (new_y + dy < 0) + dy = -new_y; + } + + if (crop_location == CropLocation.TOP_RIGHT || + crop_location == CropLocation.RIGHT || + crop_location == CropLocation.BOTTOM_RIGHT) + { + if (dx < min_size - new_w) + dx = min_size - new_w; + if (new_x + new_w + dx > pw) + dx = pw - new_x - new_w; + } + if (crop_location == CropLocation.BOTTOM_LEFT || + crop_location == CropLocation.BOTTOM || + crop_location == CropLocation.BOTTOM_RIGHT) + { + if (dy < min_size - new_h) + dy = min_size - new_h; + if (new_y + new_h + dy > ph) + dy = ph - new_y - new_h; + } + if (crop_location == CropLocation.MIDDLE) + { + if (new_x + dx + new_w > pw) + dx = pw - new_x - new_w; + if (new_x + dx < 0) + dx = -new_x; + if (new_y + dy + new_h > ph) + dy = ph - new_y - new_h; + if (new_y + dy < 0) + dy = -new_y; + } + + /* Move crop */ + if (crop_location == CropLocation.MIDDLE) + { + new_x += dx; + new_y += dy; + } + if (crop_location == CropLocation.TOP_LEFT || + crop_location == CropLocation.LEFT || + crop_location == CropLocation.BOTTOM_LEFT) + { + new_x += dx; + new_w -= dx; + } + if (crop_location == CropLocation.TOP_LEFT || + crop_location == CropLocation.TOP || + crop_location == CropLocation.TOP_RIGHT) + { + new_y += dy; + new_h -= dy; + } + + if (crop_location == CropLocation.TOP_RIGHT || + crop_location == CropLocation.RIGHT || + crop_location == CropLocation.BOTTOM_RIGHT) + new_w += dx; + if (crop_location == CropLocation.BOTTOM_LEFT || + crop_location == CropLocation.BOTTOM || + crop_location == CropLocation.BOTTOM_RIGHT) + new_h += dy; + + page.move_crop (new_x, new_y); + + /* If reshaped crop, must be a custom crop */ + if (new_w != cw || new_h != ch) + page.set_custom_crop (new_w, new_h); + } + + public void button_release (int x, int y) + { + /* Complete crop */ + crop_location = CropLocation.NONE; + changed (); + } + + public Gdk.CursorType get_cursor () + { + return cursor; + } + + private bool animation_cb () + { + animate_segment = (animate_segment + 1) % animate_n_segments; + changed (); + return true; + } + + private void update_animation () + { + bool animate, is_animating; + + animate = page.is_scanning () && !page.has_data (); + is_animating = animate_timeout != 0; + if (animate == is_animating) + return; + + if (animate) + { + animate_segment = 0; + if (animate_timeout == 0) + animate_timeout = Timeout.add (150, animation_cb); + } + else + { + if (animate_timeout != 0) + Source.remove (animate_timeout); + animate_timeout = 0; + } + } + + public void render (Cairo.Context context) + { + update_animation (); + update_page_view (); + + var w = get_preview_width (); + var h = get_preview_height (); + + context.set_line_width (1); + context.translate (x_offset, y_offset); + + /* Draw page border */ + context.set_source_rgb (0, 0, 0); + context.set_line_width (border_width); + context.rectangle ((double)border_width / 2, + (double)border_width / 2, + width - border_width, + height - border_width); + context.stroke (); + + /* Draw image */ + context.translate (border_width, border_width); + Gdk.cairo_set_source_pixbuf (context, image, 0, 0); + context.paint (); + + /* Draw throbber */ + if (page.is_scanning () && !page.has_data ()) + { + double outer_radius; + if (w > h) + outer_radius = 0.15 * w; + else + outer_radius = 0.15 * h; + var arc = Math.PI / animate_n_segments; + + /* Space circles */ + var x = outer_radius * Math.sin (arc); + var y = outer_radius * (Math.cos (arc) - 1.0); + var inner_radius = 0.6 * Math.sqrt (x*x + y*y); + + double offset = 0.0; + for (var i = 0; i < animate_n_segments; i++, offset += arc * 2) + { + x = w / 2 + outer_radius * Math.sin (offset); + y = h / 2 - outer_radius * Math.cos (offset); + context.arc (x, y, inner_radius, 0, 2 * Math.PI); + + if (i == animate_segment) + { + context.set_source_rgb (0.75, 0.75, 0.75); + context.fill_preserve (); + } + + context.set_source_rgb (0.5, 0.5, 0.5); + context.stroke (); + } + } + + /* Draw scan line */ + if (page.is_scanning () && page.get_scan_line () > 0) + { + var scan_line = page.get_scan_line (); + + double s; + double x1, y1, x2, y2; + switch (page.get_scan_direction ()) + { + case ScanDirection.TOP_TO_BOTTOM: + s = page_to_screen_y (scan_line); + x1 = 0; y1 = s + 0.5; + x2 = w; y2 = s + 0.5; + break; + case ScanDirection.BOTTOM_TO_TOP: + s = page_to_screen_y (scan_line); + x1 = 0; y1 = h - s + 0.5; + x2 = w; y2 = h - s + 0.5; + break; + case ScanDirection.LEFT_TO_RIGHT: + s = page_to_screen_x (scan_line); + x1 = s + 0.5; y1 = 0; + x2 = s + 0.5; y2 = h; + break; + case ScanDirection.RIGHT_TO_LEFT: + s = page_to_screen_x (scan_line); + x1 = w - s + 0.5; y1 = 0; + x2 = w - s + 0.5; y2 = h; + break; + default: + x1 = y1 = x2 = y2 = 0; + break; + } + + context.move_to (x1, y1); + context.line_to (x2, y2); + context.set_source_rgb (1.0, 0.0, 0.0); + context.stroke (); + } + + /* Draw crop */ + if (page.has_crop ()) + { + int x, y, crop_width, crop_height; + page.get_crop (out x, out y, out crop_width, out crop_height); + + var dx = page_to_screen_x (x); + var dy = page_to_screen_y (y); + var dw = page_to_screen_x (crop_width); + var dh = page_to_screen_y (crop_height); + + /* Shade out cropped area */ + context.rectangle (0, 0, w, h); + context.new_sub_path (); + context.rectangle (dx, dy, dw, dh); + context.set_fill_rule (Cairo.FillRule.EVEN_ODD); + context.set_source_rgba (0.25, 0.25, 0.25, 0.2); + context.fill (); + + /* Show new edge */ + context.rectangle (dx - 1.5, dy - 1.5, dw + 3, dh + 3); + context.set_source_rgb (1.0, 1.0, 1.0); + context.stroke (); + context.rectangle (dx - 0.5, dy - 0.5, dw + 1, dh + 1); + context.set_source_rgb (0.0, 0.0, 0.0); + context.stroke (); + } + } + + public void set_width (int width) + { + // FIXME: Automatically update when get updated image + var height = (int) ((double)width * page.get_height () / page.get_width ()); + if (this.width == width && this.height == height) + return; + + this.width = width; + this.height = height; + + /* Regenerate image */ + update_image = true; + + size_changed (); + changed (); + } + + public void set_height (int height) + { + // FIXME: Automatically update when get updated image + var width = (int) ((double)height * page.get_width () / page.get_height ()); + if (this.width == width && this.height == height) + return; + + this.width = width; + this.height = height; + + /* Regenerate image */ + update_image = true; + + size_changed (); + changed (); + } + + public int get_width () + { + return width; + } + + public int get_height () + { + return height; + } + + private void page_pixels_changed_cb (Page p) + { + /* Regenerate image */ + update_image = true; + changed (); + } + + private void page_size_changed_cb (Page p) + { + /* Regenerate image */ + update_image = true; + size_changed (); + changed (); + } + + private void page_overlay_changed_cb (Page p) + { + changed (); + } + + private void scan_direction_changed_cb (Page p) + { + /* Regenerate image */ + update_image = true; + size_changed (); + changed (); + } +} @@ -1,7 +1,10 @@ +/* page.c generated by valac 0.13.1, the Vala compiler + * generated from page.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later @@ -9,902 +12,1924 @@ * license. */ +#include <glib.h> +#include <glib-object.h> +#include <stdlib.h> #include <string.h> -#include "page.h" - -enum { - PIXELS_CHANGED, - SIZE_CHANGED, - SCAN_LINE_CHANGED, - SCAN_DIRECTION_CHANGED, - CROP_CHANGED, - LAST_SIGNAL +#include <float.h> +#include <math.h> +#include <gdk-pixbuf/gdk-pixdata.h> +#include <glib/gstdio.h> +#include <gio/gio.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; +typedef struct _PagePrivate PagePrivate; +#define _g_free0(var) (var = (g_free (var), NULL)) + +#define TYPE_SCAN_PAGE_INFO (scan_page_info_get_type ()) +#define SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfo)) +#define SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) +#define IS_SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_PAGE_INFO)) +#define IS_SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_PAGE_INFO)) +#define SCAN_PAGE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) + +typedef struct _ScanPageInfo ScanPageInfo; +typedef struct _ScanPageInfoClass ScanPageInfoClass; +typedef struct _ScanPageInfoPrivate ScanPageInfoPrivate; + +#define TYPE_SCAN_LINE (scan_line_get_type ()) +#define SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_LINE, ScanLine)) +#define SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_LINE, ScanLineClass)) +#define IS_SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_LINE)) +#define IS_SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_LINE)) +#define SCAN_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_LINE, ScanLineClass)) + +typedef struct _ScanLine ScanLine; +typedef struct _ScanLineClass ScanLineClass; +typedef struct _ScanLinePrivate ScanLinePrivate; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) + +#define TYPE_PIXBUF_WRITER (pixbuf_writer_get_type ()) +#define PIXBUF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PIXBUF_WRITER, PixbufWriter)) +#define PIXBUF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PIXBUF_WRITER, PixbufWriterClass)) +#define IS_PIXBUF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PIXBUF_WRITER)) +#define IS_PIXBUF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PIXBUF_WRITER)) +#define PIXBUF_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PIXBUF_WRITER, PixbufWriterClass)) + +typedef struct _PixbufWriter PixbufWriter; +typedef struct _PixbufWriterClass PixbufWriterClass; +#define _pixbuf_writer_unref0(var) ((var == NULL) ? NULL : (var = (pixbuf_writer_unref (var), NULL))) +typedef struct _ParamSpecPage ParamSpecPage; +typedef struct _PixbufWriterPrivate PixbufWriterPrivate; +typedef struct _ParamSpecPixbufWriter ParamSpecPixbufWriter; + +typedef enum { + SCAN_DIRECTION_TOP_TO_BOTTOM, + SCAN_DIRECTION_LEFT_TO_RIGHT, + SCAN_DIRECTION_BOTTOM_TO_TOP, + SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _Page { + GTypeInstance parent_instance; + volatile int ref_count; + PagePrivate * priv; }; -static guint signals[LAST_SIGNAL] = { 0, }; -struct PagePrivate -{ - /* Resolution of page */ - gint dpi; +struct _PageClass { + GTypeClass parent_class; + void (*finalize) (Page *self); +}; - /* Number of rows in this page or -1 if currently unknown */ - gint expected_rows; +struct _PagePrivate { + gint dpi; + gint expected_rows; + gint depth; + gchar* color_profile; + gint width; + gint n_rows; + gint rowstride; + gint n_channels; + guchar* pixels; + gint pixels_length1; + gint _pixels_size_; + gboolean scanning; + gboolean has_data_; + gint scan_line; + ScanDirection scan_direction; + gboolean has_crop_; + gchar* crop_name; + gint crop_x; + gint crop_y; + gint crop_width; + gint crop_height; +}; - /* Bit depth */ - gint depth; +struct _ScanPageInfo { + GTypeInstance parent_instance; + volatile int ref_count; + ScanPageInfoPrivate * priv; + gint width; + gint height; + gint depth; + gint n_channels; + gdouble dpi; + gchar* device; +}; - /* Color profile */ - gchar *color_profile; +struct _ScanPageInfoClass { + GTypeClass parent_class; + void (*finalize) (ScanPageInfo *self); +}; + +struct _ScanLine { + GTypeInstance parent_instance; + volatile int ref_count; + ScanLinePrivate * priv; + gint number; + gint n_lines; + gint width; + gint depth; + gint channel; + guchar* data; + gint data_length1; + gint data_length; +}; + +struct _ScanLineClass { + GTypeClass parent_class; + void (*finalize) (ScanLine *self); +}; - /* Scanned image data */ - gint width, n_rows, rowstride, n_channels; - guchar *pixels; +struct _ParamSpecPage { + GParamSpec parent_instance; +}; - /* Page is getting data */ - gboolean scanning; +struct _PixbufWriter { + GTypeInstance parent_instance; + volatile int ref_count; + PixbufWriterPrivate * priv; + GFileOutputStream* stream; +}; - /* TRUE if have some page data */ - gboolean has_data; +struct _PixbufWriterClass { + GTypeClass parent_class; + void (*finalize) (PixbufWriter *self); +}; - /* Expected next scan row */ - gint scan_line; +struct _ParamSpecPixbufWriter { + GParamSpec parent_instance; +}; - /* Rotation of scanned data */ - ScanDirection scan_direction; - /* Crop */ - gboolean has_crop; - gchar *crop_name; - gint crop_x, crop_y, crop_width, crop_height; +static gpointer page_parent_class = NULL; +static gpointer pixbuf_writer_parent_class = NULL; + +GType scan_direction_get_type (void) G_GNUC_CONST; +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +#define PAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PAGE, PagePrivate)) +enum { + PAGE_DUMMY_PROPERTY +}; +Page* page_new (gint width, gint height, gint dpi, ScanDirection scan_direction); +Page* page_construct (GType object_type, gint width, gint height, gint dpi, ScanDirection scan_direction); +gpointer scan_page_info_ref (gpointer instance); +void scan_page_info_unref (gpointer instance); +GParamSpec* param_spec_scan_page_info (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_page_info (GValue* value, gpointer v_object); +void value_take_scan_page_info (GValue* value, gpointer v_object); +gpointer value_get_scan_page_info (const GValue* value); +GType scan_page_info_get_type (void) G_GNUC_CONST; +void page_set_page_info (Page* self, ScanPageInfo* info); +void page_start (Page* self); +gboolean page_is_scanning (Page* self); +gboolean page_has_data (Page* self); +gboolean page_is_color (Page* self); +gint page_get_scan_line (Page* self); +gpointer scan_line_ref (gpointer instance); +void scan_line_unref (gpointer instance); +GParamSpec* param_spec_scan_line (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_line (GValue* value, gpointer v_object); +void value_take_scan_line (GValue* value, gpointer v_object); +gpointer value_get_scan_line (const GValue* value); +GType scan_line_get_type (void) G_GNUC_CONST; +static void page_parse_line (Page* self, ScanLine* line, gint n, gboolean* size_changed); +gint page_get_scan_height (Page* self); +void page_parse_scan_line (Page* self, ScanLine* line); +void page_finish (Page* self); +ScanDirection page_get_scan_direction (Page* self); +static void page_set_scan_direction (Page* self, ScanDirection direction); +gint page_get_width (Page* self); +gint page_get_height (Page* self); +void page_rotate_left (Page* self); +void page_rotate_right (Page* self); +gint page_get_dpi (Page* self); +gboolean page_is_landscape (Page* self); +gint page_get_depth (Page* self); +gint page_get_n_channels (Page* self); +gint page_get_rowstride (Page* self); +gint page_get_scan_width (Page* self); +void page_set_color_profile (Page* self, const gchar* color_profile); +gchar* page_get_color_profile (Page* self); +void page_set_no_crop (Page* self); +void page_set_custom_crop (Page* self, gint width, gint height); +void page_set_named_crop (Page* self, const gchar* name); +void page_move_crop (Page* self, gint x, gint y); +void page_rotate_crop (Page* self); +gboolean page_has_crop (Page* self); +void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height); +gchar* page_get_named_crop (Page* self); +guchar* page_get_pixels (Page* self, int* result_length1); +static guchar page_get_sample (Page* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint n_channels, gint channel); +static void page_get_pixel (Page* self, gint x, gint y, guchar* pixel, int pixel_length1, gint offset); +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop); +static gchar* page_get_icc_data_encoded (Page* self, const gchar* icc_profile_filename); +void page_save (Page* self, const gchar* type, GFile* file, GError** error); +PixbufWriter* pixbuf_writer_new (GFileOutputStream* stream); +PixbufWriter* pixbuf_writer_construct (GType object_type, GFileOutputStream* stream); +gpointer pixbuf_writer_ref (gpointer instance); +void pixbuf_writer_unref (gpointer instance); +GParamSpec* param_spec_pixbuf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_pixbuf_writer (GValue* value, gpointer v_object); +void value_take_pixbuf_writer (GValue* value, gpointer v_object); +gpointer value_get_pixbuf_writer (const GValue* value); +GType pixbuf_writer_get_type (void) G_GNUC_CONST; +void pixbuf_writer_save (PixbufWriter* self, GdkPixbuf* image, const gchar* type, gchar** option_keys, int option_keys_length1, gchar** option_values, int option_values_length1, GError** error); +static void page_finalize (Page* obj); +enum { + PIXBUF_WRITER_DUMMY_PROPERTY }; +static gboolean pixbuf_writer_write_pixbuf_data (PixbufWriter* self, guint8* buf, int buf_length1, GError** error); +static gboolean _pixbuf_writer_write_pixbuf_data_gdk_pixbuf_save_func (guint8* buf, gsize buf_length1, GError** error, gpointer self); +static void pixbuf_writer_finalize (PixbufWriter* obj); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); + + +GType scan_direction_get_type (void) { + static volatile gsize scan_direction_type_id__volatile = 0; + if (g_once_init_enter (&scan_direction_type_id__volatile)) { + static const GEnumValue values[] = {{SCAN_DIRECTION_TOP_TO_BOTTOM, "SCAN_DIRECTION_TOP_TO_BOTTOM", "top-to-bottom"}, {SCAN_DIRECTION_LEFT_TO_RIGHT, "SCAN_DIRECTION_LEFT_TO_RIGHT", "left-to-right"}, {SCAN_DIRECTION_BOTTOM_TO_TOP, "SCAN_DIRECTION_BOTTOM_TO_TOP", "bottom-to-top"}, {SCAN_DIRECTION_RIGHT_TO_LEFT, "SCAN_DIRECTION_RIGHT_TO_LEFT", "right-to-left"}, {0, NULL, NULL}}; + GType scan_direction_type_id; + scan_direction_type_id = g_enum_register_static ("ScanDirection", values); + g_once_init_leave (&scan_direction_type_id__volatile, scan_direction_type_id); + } + return scan_direction_type_id__volatile; +} + + +Page* page_construct (GType object_type, gint width, gint height, gint dpi, ScanDirection scan_direction) { + Page* self = NULL; + gboolean _tmp0_ = FALSE; + self = (Page*) g_type_create_instance (object_type); + if (scan_direction == SCAN_DIRECTION_TOP_TO_BOTTOM) { + _tmp0_ = TRUE; + } else { + _tmp0_ = scan_direction == SCAN_DIRECTION_BOTTOM_TO_TOP; + } + if (_tmp0_) { + self->priv->width = width; + self->priv->n_rows = height; + } else { + self->priv->width = height; + self->priv->n_rows = width; + } + self->priv->dpi = dpi; + self->priv->scan_direction = scan_direction; + return self; +} + + +Page* page_new (gint width, gint height, gint dpi, ScanDirection scan_direction) { + return page_construct (TYPE_PAGE, width, height, dpi, scan_direction); +} + + +void page_set_page_info (Page* self, ScanPageInfo* info) { + gint _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (info != NULL); + self->priv->expected_rows = info->height; + self->priv->dpi = (gint) info->dpi; + self->priv->width = info->width; + self->priv->n_rows = info->height; + if (self->priv->n_rows < 0) { + self->priv->n_rows = self->priv->width / 2; + } + self->priv->depth = info->depth; + self->priv->n_channels = info->n_channels; + self->priv->rowstride = (((self->priv->width * self->priv->depth) * self->priv->n_channels) + 7) / 8; + _tmp0_ = self->priv->n_rows * self->priv->rowstride; + self->priv->pixels = g_renew (guchar, self->priv->pixels, self->priv->n_rows * self->priv->rowstride); + (_tmp0_ > self->priv->pixels_length1) ? memset (self->priv->pixels + self->priv->pixels_length1, 0, sizeof (guchar) * (_tmp0_ - self->priv->pixels_length1)) : NULL; + self->priv->pixels_length1 = _tmp0_; + self->priv->_pixels_size_ = _tmp0_; + g_return_if_fail (self->priv->pixels != NULL); + if (self->priv->depth == 1) { + memset (self->priv->pixels, 0x00, (gsize) (self->priv->n_rows * self->priv->rowstride)); + } else { + memset (self->priv->pixels, 0xFF, (gsize) (self->priv->n_rows * self->priv->rowstride)); + } + g_signal_emit_by_name (self, "size-changed"); + g_signal_emit_by_name (self, "pixels-changed"); +} + + +void page_start (Page* self) { + g_return_if_fail (self != NULL); + self->priv->scanning = TRUE; + g_signal_emit_by_name (self, "scan-line-changed"); +} + + +gboolean page_is_scanning (Page* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->scanning; + return result; +} + + +gboolean page_has_data (Page* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->has_data_; + return result; +} + + +gboolean page_is_color (Page* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->n_channels > 1; + return result; +} + + +gint page_get_scan_line (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->scan_line; + return result; +} + + +static void page_parse_line (Page* self, ScanLine* line, gint n, gboolean* size_changed) { + gboolean _size_changed = FALSE; + gint line_number = 0; + gint offset; + gint line_offset; + g_return_if_fail (self != NULL); + g_return_if_fail (line != NULL); + line_number = line->number + n; + _size_changed = FALSE; + while (TRUE) { + gint _tmp0_; + gint rows = 0; + gint _tmp1_; + _tmp0_ = page_get_scan_height (self); + if (!(line_number >= _tmp0_)) { + break; + } + rows = self->priv->n_rows; + self->priv->n_rows = rows + (self->priv->width / 2); + g_debug ("page.vala:151: Extending image from %d lines to %d lines", rows, self->priv->n_rows); + _tmp1_ = self->priv->n_rows * self->priv->rowstride; + self->priv->pixels = g_renew (guchar, self->priv->pixels, self->priv->n_rows * self->priv->rowstride); + (_tmp1_ > self->priv->pixels_length1) ? memset (self->priv->pixels + self->priv->pixels_length1, 0, sizeof (guchar) * (_tmp1_ - self->priv->pixels_length1)) : NULL; + self->priv->pixels_length1 = _tmp1_; + self->priv->_pixels_size_ = _tmp1_; + _size_changed = TRUE; + } + offset = line_number * self->priv->rowstride; + line_offset = n * line->data_length; + { + gint i; + i = 0; + { + gboolean _tmp2_; + _tmp2_ = TRUE; + while (TRUE) { + if (!_tmp2_) { + i++; + } + _tmp2_ = FALSE; + if (!(i < line->data_length)) { + break; + } + self->priv->pixels[offset + i] = line->data[line_offset + i]; + } + } + } + self->priv->scan_line = line_number; + if (size_changed) { + *size_changed = _size_changed; + } +} + + +void page_parse_scan_line (Page* self, ScanLine* line) { + gboolean size_has_changed; + g_return_if_fail (self != NULL); + g_return_if_fail (line != NULL); + size_has_changed = FALSE; + { + gint i; + i = 0; + { + gboolean _tmp0_; + _tmp0_ = TRUE; + while (TRUE) { + gboolean _tmp1_; + if (!_tmp0_) { + i++; + } + _tmp0_ = FALSE; + if (!(i < line->n_lines)) { + break; + } + page_parse_line (self, line, i, &_tmp1_); + size_has_changed = _tmp1_; + } + } + } + self->priv->has_data_ = TRUE; + if (size_has_changed) { + g_signal_emit_by_name (self, "size-changed"); + } + g_signal_emit_by_name (self, "scan-line-changed"); + g_signal_emit_by_name (self, "pixels-changed"); +} + + +void page_finish (Page* self) { + gboolean size_has_changed; + gboolean _tmp0_ = FALSE; + g_return_if_fail (self != NULL); + size_has_changed = FALSE; + if (self->priv->expected_rows < 0) { + gint _tmp1_; + _tmp1_ = page_get_scan_height (self); + _tmp0_ = self->priv->scan_line != _tmp1_; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + gint rows = 0; + gint _tmp2_; + rows = self->priv->n_rows; + self->priv->n_rows = self->priv->scan_line; + _tmp2_ = self->priv->n_rows * self->priv->rowstride; + self->priv->pixels = g_renew (guchar, self->priv->pixels, self->priv->n_rows * self->priv->rowstride); + (_tmp2_ > self->priv->pixels_length1) ? memset (self->priv->pixels + self->priv->pixels_length1, 0, sizeof (guchar) * (_tmp2_ - self->priv->pixels_length1)) : NULL; + self->priv->pixels_length1 = _tmp2_; + self->priv->_pixels_size_ = _tmp2_; + g_debug ("page.vala:193: Trimming page from %d lines to %d lines", rows, self->priv->n_rows); + size_has_changed = TRUE; + } + self->priv->scanning = FALSE; + if (size_has_changed) { + g_signal_emit_by_name (self, "size-changed"); + } + g_signal_emit_by_name (self, "scan-line-changed"); +} + + +ScanDirection page_get_scan_direction (Page* self) { + ScanDirection result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->scan_direction; + return result; +} + + +static void page_set_scan_direction (Page* self, ScanDirection direction) { + gint left_steps = 0; + gint t = 0; + gboolean size_has_changed; + gint width = 0; + gint height = 0; + gint _tmp0_; + gint _tmp1_; + g_return_if_fail (self != NULL); + size_has_changed = FALSE; + if (self->priv->scan_direction == direction) { + return; + } + left_steps = (gint) (direction - self->priv->scan_direction); + if (left_steps < 0) { + left_steps = left_steps + 4; + } + if (left_steps != 2) { + size_has_changed = TRUE; + } + _tmp0_ = page_get_width (self); + width = _tmp0_; + _tmp1_ = page_get_height (self); + height = _tmp1_; + if (self->priv->has_crop_) { + switch (left_steps) { + case 1: + { + t = self->priv->crop_x; + self->priv->crop_x = self->priv->crop_y; + self->priv->crop_y = width - (t + self->priv->crop_width); + t = self->priv->crop_width; + self->priv->crop_width = self->priv->crop_height; + self->priv->crop_height = t; + break; + } + case 2: + { + self->priv->crop_x = width - (self->priv->crop_x + self->priv->crop_width); + self->priv->crop_y = width - (self->priv->crop_y + self->priv->crop_height); + break; + } + case 3: + { + t = self->priv->crop_y; + self->priv->crop_y = self->priv->crop_x; + self->priv->crop_x = height - (t + self->priv->crop_height); + t = self->priv->crop_width; + self->priv->crop_width = self->priv->crop_height; + self->priv->crop_height = t; + break; + } + default: + break; + } + } + self->priv->scan_direction = direction; + if (size_has_changed) { + g_signal_emit_by_name (self, "size-changed"); + } + g_signal_emit_by_name (self, "scan-direction-changed"); + if (self->priv->has_crop_) { + g_signal_emit_by_name (self, "crop-changed"); + } +} + + +void page_rotate_left (Page* self) { + ScanDirection direction; + g_return_if_fail (self != NULL); + direction = self->priv->scan_direction; + switch (direction) { + case SCAN_DIRECTION_TOP_TO_BOTTOM: + { + direction = SCAN_DIRECTION_LEFT_TO_RIGHT; + break; + } + case SCAN_DIRECTION_LEFT_TO_RIGHT: + { + direction = SCAN_DIRECTION_BOTTOM_TO_TOP; + break; + } + case SCAN_DIRECTION_BOTTOM_TO_TOP: + { + direction = SCAN_DIRECTION_RIGHT_TO_LEFT; + break; + } + case SCAN_DIRECTION_RIGHT_TO_LEFT: + { + direction = SCAN_DIRECTION_TOP_TO_BOTTOM; + break; + } + default: + break; + } + page_set_scan_direction (self, direction); +} + + +void page_rotate_right (Page* self) { + ScanDirection direction; + g_return_if_fail (self != NULL); + direction = self->priv->scan_direction; + switch (direction) { + case SCAN_DIRECTION_TOP_TO_BOTTOM: + { + direction = SCAN_DIRECTION_RIGHT_TO_LEFT; + break; + } + case SCAN_DIRECTION_LEFT_TO_RIGHT: + { + direction = SCAN_DIRECTION_TOP_TO_BOTTOM; + break; + } + case SCAN_DIRECTION_BOTTOM_TO_TOP: + { + direction = SCAN_DIRECTION_LEFT_TO_RIGHT; + break; + } + case SCAN_DIRECTION_RIGHT_TO_LEFT: + { + direction = SCAN_DIRECTION_BOTTOM_TO_TOP; + break; + } + default: + break; + } + page_set_scan_direction (self, direction); +} + + +gint page_get_dpi (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->dpi; + return result; +} + + +gboolean page_is_landscape (Page* self) { + gboolean result = FALSE; + gint _tmp0_; + gint _tmp1_; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = page_get_width (self); + _tmp1_ = page_get_height (self); + result = _tmp0_ > _tmp1_; + return result; +} + + +gint page_get_width (Page* self) { + gint result = 0; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, 0); + if (self->priv->scan_direction == SCAN_DIRECTION_TOP_TO_BOTTOM) { + _tmp0_ = TRUE; + } else { + _tmp0_ = self->priv->scan_direction == SCAN_DIRECTION_BOTTOM_TO_TOP; + } + if (_tmp0_) { + result = self->priv->width; + return result; + } else { + result = self->priv->n_rows; + return result; + } +} + + +gint page_get_height (Page* self) { + gint result = 0; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, 0); + if (self->priv->scan_direction == SCAN_DIRECTION_TOP_TO_BOTTOM) { + _tmp0_ = TRUE; + } else { + _tmp0_ = self->priv->scan_direction == SCAN_DIRECTION_BOTTOM_TO_TOP; + } + if (_tmp0_) { + result = self->priv->n_rows; + return result; + } else { + result = self->priv->width; + return result; + } +} + + +gint page_get_depth (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->depth; + return result; +} + + +gint page_get_n_channels (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->n_channels; + return result; +} + + +gint page_get_rowstride (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->rowstride; + return result; +} -G_DEFINE_TYPE (Page, page, G_TYPE_OBJECT); +gint page_get_scan_width (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->width; + return result; +} -Page * -page_new (gint width, gint height, gint dpi, ScanDirection scan_direction) -{ - Page *page; - - page = g_object_new (PAGE_TYPE, NULL); - if (scan_direction == TOP_TO_BOTTOM || scan_direction == BOTTOM_TO_TOP) { - page->priv->width = width; - page->priv->n_rows = height; - } - else { - page->priv->width = height; - page->priv->n_rows = width; - } - page->priv->dpi = dpi; - page->priv->scan_direction = scan_direction; - return page; +gint page_get_scan_height (Page* self) { + gint result = 0; + g_return_val_if_fail (self != NULL, 0); + result = self->priv->n_rows; + return result; } -void -page_set_page_info (Page *page, ScanPageInfo *info) -{ - g_return_if_fail (page != NULL); +void page_set_color_profile (Page* self, const gchar* color_profile) { + gchar* _tmp0_; + g_return_if_fail (self != NULL); + _tmp0_ = g_strdup (color_profile); + _g_free0 (self->priv->color_profile); + self->priv->color_profile = _tmp0_; +} - page->priv->expected_rows = info->height; - page->priv->dpi = info->dpi; - /* Create a white page */ - page->priv->width = info->width; - page->priv->n_rows = info->height; - /* Variable height, try 50% of the width for now */ - if (page->priv->n_rows < 0) - page->priv->n_rows = page->priv->width / 2; - page->priv->depth = info->depth; - page->priv->n_channels = info->n_channels; - page->priv->rowstride = (page->priv->width * page->priv->depth * page->priv->n_channels + 7) / 8; - page->priv->pixels = g_realloc (page->priv->pixels, page->priv->n_rows * page->priv->rowstride); - g_return_if_fail (page->priv->pixels != NULL); +gchar* page_get_color_profile (Page* self) { + gchar* result = NULL; + gchar* _tmp0_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = g_strdup (self->priv->color_profile); + result = _tmp0_; + return result; +} - /* Fill with white */ - if (page->priv->depth == 1) - memset (page->priv->pixels, 0x00, page->priv->n_rows * page->priv->rowstride); - else - memset (page->priv->pixels, 0xFF, page->priv->n_rows * page->priv->rowstride); - g_signal_emit (page, signals[SIZE_CHANGED], 0); - g_signal_emit (page, signals[PIXELS_CHANGED], 0); +void page_set_no_crop (Page* self) { + g_return_if_fail (self != NULL); + if (!self->priv->has_crop_) { + return; + } + self->priv->has_crop_ = FALSE; + g_signal_emit_by_name (self, "crop-changed"); } -void -page_start (Page *page) -{ - g_return_if_fail (page != NULL); +void page_set_custom_crop (Page* self, gint width, gint height) { + gboolean _tmp0_ = FALSE; + gboolean _tmp1_ = FALSE; + gboolean _tmp2_ = FALSE; + g_return_if_fail (self != NULL); + g_return_if_fail (width >= 1); + g_return_if_fail (height >= 1); + if (self->priv->crop_name == NULL) { + _tmp2_ = self->priv->has_crop_; + } else { + _tmp2_ = FALSE; + } + if (_tmp2_) { + _tmp1_ = self->priv->crop_width == width; + } else { + _tmp1_ = FALSE; + } + if (_tmp1_) { + _tmp0_ = self->priv->crop_height == height; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + return; + } + _g_free0 (self->priv->crop_name); + self->priv->crop_name = NULL; + self->priv->has_crop_ = TRUE; + self->priv->crop_width = width; + self->priv->crop_height = height; + g_signal_emit_by_name (self, "crop-changed"); +} + - page->priv->scanning = TRUE; - g_signal_emit (page, signals[SCAN_LINE_CHANGED], 0); +void page_set_named_crop (Page* self, const gchar* name) { + gdouble width = 0.0; + gdouble height = 0.0; + const gchar* _tmp0_; + GQuark _tmp1_; + static GQuark _tmp1__label0 = 0; + static GQuark _tmp1__label1 = 0; + static GQuark _tmp1__label2 = 0; + static GQuark _tmp1__label3 = 0; + static GQuark _tmp1__label4 = 0; + static GQuark _tmp1__label5 = 0; + gchar* _tmp2_; + gint _tmp3_; + gint pw; + gint _tmp4_; + gint ph; + g_return_if_fail (self != NULL); + g_return_if_fail (name != NULL); + _tmp0_ = name; + _tmp1_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_); + if (_tmp1_ == ((0 != _tmp1__label0) ? _tmp1__label0 : (_tmp1__label0 = g_quark_from_static_string ("A4")))) { + switch (0) { + default: + { + width = 8.3; + height = 11.7; + break; + } + } + } else if (_tmp1_ == ((0 != _tmp1__label1) ? _tmp1__label1 : (_tmp1__label1 = g_quark_from_static_string ("A5")))) { + switch (0) { + default: + { + width = 5.8; + height = 8.3; + break; + } + } + } else if (_tmp1_ == ((0 != _tmp1__label2) ? _tmp1__label2 : (_tmp1__label2 = g_quark_from_static_string ("A6")))) { + switch (0) { + default: + { + width = 4.1; + height = 5.8; + break; + } + } + } else if (_tmp1_ == ((0 != _tmp1__label3) ? _tmp1__label3 : (_tmp1__label3 = g_quark_from_static_string ("letter")))) { + switch (0) { + default: + { + width = 8.5; + height = (gdouble) 11; + break; + } + } + } else if (_tmp1_ == ((0 != _tmp1__label4) ? _tmp1__label4 : (_tmp1__label4 = g_quark_from_static_string ("legal")))) { + switch (0) { + default: + { + width = 8.5; + height = (gdouble) 14; + break; + } + } + } else if (_tmp1_ == ((0 != _tmp1__label5) ? _tmp1__label5 : (_tmp1__label5 = g_quark_from_static_string ("4x6")))) { + switch (0) { + default: + { + width = (gdouble) 4; + height = (gdouble) 6; + break; + } + } + } else { + switch (0) { + default: + { + g_warning ("page.vala:437: Unknown paper size '%s'", name); + return; + } + } + } + _tmp2_ = g_strdup (name); + _g_free0 (self->priv->crop_name); + self->priv->crop_name = _tmp2_; + self->priv->has_crop_ = TRUE; + _tmp3_ = page_get_width (self); + pw = _tmp3_; + _tmp4_ = page_get_height (self); + ph = _tmp4_; + if (pw > ph) { + gdouble t = 0.0; + t = width; + width = height; + height = t; + } + self->priv->crop_width = (gint) ((width * self->priv->dpi) + 0.5); + self->priv->crop_height = (gint) ((height * self->priv->dpi) + 0.5); + if (self->priv->crop_width < pw) { + self->priv->crop_x = (pw - self->priv->crop_width) / 2; + } else { + self->priv->crop_x = 0; + } + if (self->priv->crop_height < ph) { + self->priv->crop_y = (ph - self->priv->crop_height) / 2; + } else { + self->priv->crop_y = 0; + } + g_signal_emit_by_name (self, "crop-changed"); } -gboolean -page_is_scanning (Page *page) -{ - g_return_val_if_fail (page != NULL, FALSE); - - return page->priv->scanning; +void page_move_crop (Page* self, gint x, gint y) { + gint _tmp0_; + gint _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (x >= 0); + g_return_if_fail (y >= 0); + _tmp0_ = page_get_width (self); + g_return_if_fail (x < _tmp0_); + _tmp1_ = page_get_height (self); + g_return_if_fail (y < _tmp1_); + self->priv->crop_x = x; + self->priv->crop_y = y; + g_signal_emit_by_name (self, "crop-changed"); } -gboolean -page_has_data (Page *page) -{ - g_return_val_if_fail (page != NULL, FALSE); - return page->priv->has_data; +void page_rotate_crop (Page* self) { + gint t = 0; + g_return_if_fail (self != NULL); + if (!self->priv->has_crop_) { + return; + } + t = self->priv->crop_width; + self->priv->crop_width = self->priv->crop_height; + self->priv->crop_height = t; + if (self->priv->crop_name == NULL) { + gint w = 0; + gint h = 0; + gint _tmp0_; + gint _tmp1_; + _tmp0_ = page_get_width (self); + w = _tmp0_; + _tmp1_ = page_get_height (self); + h = _tmp1_; + if ((self->priv->crop_x + self->priv->crop_width) > w) { + self->priv->crop_x = w - self->priv->crop_width; + } + if (self->priv->crop_x < 0) { + self->priv->crop_x = 0; + self->priv->crop_width = w; + } + if ((self->priv->crop_y + self->priv->crop_height) > h) { + self->priv->crop_y = h - self->priv->crop_height; + } + if (self->priv->crop_y < 0) { + self->priv->crop_y = 0; + self->priv->crop_height = h; + } + } + g_signal_emit_by_name (self, "crop-changed"); } -gboolean -page_is_color (Page *page) -{ - g_return_val_if_fail (page != NULL, FALSE); - return page->priv->n_channels > 1; +gboolean page_has_crop (Page* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->has_crop_; + return result; } -gint -page_get_scan_line (Page *page) -{ - g_return_val_if_fail (page != NULL, -1); - return page->priv->scan_line; +void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height) { + gint _x = 0; + gint _y = 0; + gint _width = 0; + gint _height = 0; + g_return_if_fail (self != NULL); + _x = self->priv->crop_x; + _y = self->priv->crop_y; + _width = self->priv->crop_width; + _height = self->priv->crop_height; + if (x) { + *x = _x; + } + if (y) { + *y = _y; + } + if (width) { + *width = _width; + } + if (height) { + *height = _height; + } } -static void -parse_line (Page *page, ScanLine *line, gint n, gboolean *size_changed) -{ - gint line_number; +gchar* page_get_named_crop (Page* self) { + gchar* result = NULL; + gchar* _tmp0_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = g_strdup (self->priv->crop_name); + result = _tmp0_; + return result; +} + + +guchar* page_get_pixels (Page* self, int* result_length1) { + guchar* result = NULL; + guchar* _tmp0_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->pixels; + if (result_length1) { + *result_length1 = self->priv->pixels_length1; + } + result = _tmp0_; + return result; +} + + +static guchar page_get_sample (Page* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint n_channels, gint channel) { + guchar result = '\0'; + g_return_val_if_fail (self != NULL, '\0'); + result = (guchar) 0xFF; + return result; +} + + +static void page_get_pixel (Page* self, gint x, gint y, guchar* pixel, int pixel_length1, gint offset) { + ScanDirection _tmp0_; + gint _tmp5_; + gint depth; + gint _tmp6_; + gint n_channels; + gint _tmp7_; + gint line_offset; + gboolean _tmp8_ = FALSE; + guchar _tmp14_; + guchar _tmp15_; + guchar _tmp16_; + g_return_if_fail (self != NULL); + _tmp0_ = page_get_scan_direction (self); + switch (_tmp0_) { + case SCAN_DIRECTION_TOP_TO_BOTTOM: + { + break; + } + case SCAN_DIRECTION_BOTTOM_TO_TOP: + { + gint _tmp1_; + gint _tmp2_; + _tmp1_ = page_get_scan_width (self); + x = (_tmp1_ - x) - 1; + _tmp2_ = page_get_scan_height (self); + y = (_tmp2_ - y) - 1; + break; + } + case SCAN_DIRECTION_LEFT_TO_RIGHT: + { + gint t; + gint _tmp3_; + t = x; + _tmp3_ = page_get_scan_width (self); + x = (_tmp3_ - y) - 1; + y = t; + break; + } + case SCAN_DIRECTION_RIGHT_TO_LEFT: + { + gint t; + gint _tmp4_; + t = x; + x = y; + _tmp4_ = page_get_scan_height (self); + y = (_tmp4_ - t) - 1; + break; + } + default: + break; + } + _tmp5_ = page_get_depth (self); + depth = _tmp5_; + _tmp6_ = page_get_n_channels (self); + n_channels = _tmp6_; + _tmp7_ = page_get_rowstride (self); + line_offset = _tmp7_ * y; + if (depth == 8) { + _tmp8_ = n_channels == 3; + } else { + _tmp8_ = FALSE; + } + if (_tmp8_) { + gint o; + o = line_offset + (x * n_channels); + pixel[offset + 0] = self->priv->pixels[o]; + pixel[offset + 1] = self->priv->pixels[o + 1]; + pixel[offset + 2] = self->priv->pixels[o + 2]; + return; + } else { + gboolean _tmp9_ = FALSE; + if (depth == 8) { + _tmp9_ = n_channels == 1; + } else { + _tmp9_ = FALSE; + } + if (_tmp9_) { + guchar p; + p = self->priv->pixels[line_offset + x]; + pixel[offset + 2] = p; + pixel[offset + 1] = pixel[offset + 2]; + pixel[offset + 0] = pixel[offset + 1]; + return; + } else { + gboolean _tmp10_ = FALSE; + if (depth == 1) { + _tmp10_ = n_channels == 1; + } else { + _tmp10_ = FALSE; + } + if (_tmp10_) { + guchar p; + gint _tmp11_ = 0; + p = self->priv->pixels[line_offset + (x / 8)]; + if (((gint) (p & (0x80 >> (x % 8)))) != 0) { + _tmp11_ = 0x00; + } else { + _tmp11_ = 0xFF; + } + pixel[offset + 2] = (guchar) _tmp11_; + pixel[offset + 1] = pixel[offset + 2]; + pixel[offset + 0] = pixel[offset + 1]; + return; + } else { + gboolean _tmp12_ = FALSE; + if (depth == 2) { + _tmp12_ = n_channels == 1; + } else { + _tmp12_ = FALSE; + } + if (_tmp12_) { + gint _tmp13_[4] = {0}; + gint block_shift[4]; + guchar p; + gint sample; + _tmp13_[0] = 6; + _tmp13_[1] = 4; + _tmp13_[2] = 2; + _tmp13_[3] = 0; + memcpy (block_shift, _tmp13_, 4 * sizeof (gint)); + p = self->priv->pixels[line_offset + (x / 4)]; + sample = (p >> block_shift[x % 4]) & 0x3; + sample = (sample * 255) / 3; + pixel[offset + 2] = (guchar) sample; + pixel[offset + 1] = pixel[offset + 2]; + pixel[offset + 0] = pixel[offset + 1]; + return; + } + } + } + } + _tmp14_ = page_get_sample (self, self->priv->pixels, self->priv->pixels_length1, line_offset, x, depth, n_channels, 0); + pixel[offset + 0] = _tmp14_; + _tmp15_ = page_get_sample (self, self->priv->pixels, self->priv->pixels_length1, line_offset, x, depth, n_channels, 1); + pixel[offset + 1] = _tmp15_; + _tmp16_ = page_get_sample (self, self->priv->pixels, self->priv->pixels_length1, line_offset, x, depth, n_channels, 2); + pixel[offset + 2] = _tmp16_; +} + + +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop) { + GdkPixbuf* result = NULL; + gint l = 0; + gint r = 0; + gint t = 0; + gint b = 0; + gboolean _tmp0_ = FALSE; + GdkPixbuf* _tmp7_ = NULL; + GdkPixbuf* image; + guint8* _tmp8_ = NULL; + guint8* image_pixels; + gint image_pixels_length1; + gint _image_pixels_size_; + g_return_val_if_fail (self != NULL, NULL); + if (apply_crop) { + _tmp0_ = self->priv->has_crop_; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + gint _tmp1_; + gint _tmp3_; + l = self->priv->crop_x; + r = l + self->priv->crop_width; + t = self->priv->crop_y; + b = t + self->priv->crop_height; + if (l < 0) { + l = 0; + } + _tmp1_ = page_get_width (self); + if (r > _tmp1_) { + gint _tmp2_; + _tmp2_ = page_get_width (self); + r = _tmp2_; + } + if (t < 0) { + t = 0; + } + _tmp3_ = page_get_height (self); + if (b > _tmp3_) { + gint _tmp4_; + _tmp4_ = page_get_height (self); + b = _tmp4_; + } + } else { + gint _tmp5_; + gint _tmp6_; + l = 0; + _tmp5_ = page_get_width (self); + r = _tmp5_; + t = 0; + _tmp6_ = page_get_height (self); + b = _tmp6_; + } + _tmp7_ = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, r - l, b - t); + image = _tmp7_; + _tmp8_ = gdk_pixbuf_get_pixels (image); + image_pixels = _tmp8_; + image_pixels_length1 = -1; + _image_pixels_size_ = image_pixels_length1; + { + gint y; + y = t; + { + gboolean _tmp9_; + _tmp9_ = TRUE; + while (TRUE) { + gint _tmp10_; + gint offset; + if (!_tmp9_) { + y++; + } + _tmp9_ = FALSE; + if (!(y < b)) { + break; + } + _tmp10_ = gdk_pixbuf_get_rowstride (image); + offset = _tmp10_ * (y - t); + { + gint x; + x = l; + { + gboolean _tmp11_; + _tmp11_ = TRUE; + while (TRUE) { + if (!_tmp11_) { + x++; + } + _tmp11_ = FALSE; + if (!(x < r)) { + break; + } + page_get_pixel (self, x, y, image_pixels, image_pixels_length1, offset + ((x - l) * 3)); + } + } + } + } + } + } + result = image; + return result; +} + + +static gchar* string_to_utf8 (const gchar* self, int* result_length1) { + gchar* result = NULL; + gint _tmp0_; + gchar* _tmp1_ = NULL; + gchar* _result_; + gint _result__length1; + gint __result__size_; + gint _tmp2_; + gchar* _tmp3_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = strlen (self); + _tmp1_ = g_new0 (gchar, _tmp0_ + 1); + _result_ = _tmp1_; + _result__length1 = _tmp0_ + 1; + __result__size_ = _result__length1; + _result__length1--; + _tmp2_ = strlen (self); + memcpy (_result_, self, (gsize) _tmp2_); + _tmp3_ = _result_; + if (result_length1) { + *result_length1 = _result__length1; + } + result = _tmp3_; + return result; +} + + +static gchar* page_get_icc_data_encoded (Page* self, const gchar* icc_profile_filename) { + gchar* result = NULL; + gchar* contents = NULL; + gint _tmp1_; + gchar* _tmp2_ = NULL; + guchar* _tmp3_; + gint _tmp3__length1; + gchar* _tmp4_ = NULL; + gchar* _tmp5_; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (icc_profile_filename != NULL, NULL); + { + gchar* _tmp0_ = NULL; + g_file_get_contents (icc_profile_filename, &_tmp0_, NULL, &_inner_error_); + _g_free0 (contents); + contents = _tmp0_; + if (_inner_error_ != NULL) { + goto __catch2_g_error; + } + } + goto __finally2; + __catch2_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("page.vala:670: failed to get icc profile data: %s", e->message); + result = NULL; + _g_error_free0 (e); + _g_free0 (contents); + return result; + } + __finally2: + if (_inner_error_ != NULL) { + _g_free0 (contents); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + _tmp2_ = string_to_utf8 (contents, &_tmp1_); + _tmp3_ = (guchar*) _tmp2_; + _tmp3__length1 = _tmp1_; + _tmp4_ = g_base64_encode (_tmp3_, _tmp1_); + _tmp5_ = _tmp4_; + _tmp3_ = (g_free (_tmp3_), NULL); + result = _tmp5_; + _g_free0 (contents); + return result; +} - line_number = line->number + n; - /* Extend image if necessary */ - while (line_number >= page_get_scan_height (page)) { - gint rows; +void page_save (Page* self, const gchar* type, GFile* file, GError** error) { + GFileOutputStream* _tmp0_ = NULL; + GFileOutputStream* stream; + PixbufWriter* _tmp1_ = NULL; + PixbufWriter* writer; + GdkPixbuf* _tmp2_ = NULL; + GdkPixbuf* image; + gchar* icc_profile_data; + gint _tmp4_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (type != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &_inner_error_); + stream = _tmp0_; + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + _tmp1_ = pixbuf_writer_new (stream); + writer = _tmp1_; + _tmp2_ = page_get_image (self, TRUE); + image = _tmp2_; + icc_profile_data = NULL; + if (self->priv->color_profile != NULL) { + gchar* _tmp3_ = NULL; + _tmp3_ = page_get_icc_data_encoded (self, self->priv->color_profile); + _g_free0 (icc_profile_data); + icc_profile_data = _tmp3_; + } + _tmp4_ = g_strcmp0 (type, "jpeg"); + if (_tmp4_ == 0) { + gchar* _tmp5_; + gchar** _tmp6_ = NULL; + gchar** keys; + gint keys_length1; + gint _keys_size_; + gchar* _tmp7_; + gchar** _tmp8_ = NULL; + gchar** values; + gint values_length1; + gint _values_size_; + _tmp5_ = g_strdup ("quality"); + _tmp6_ = g_new0 (gchar*, 2 + 1); + _tmp6_[0] = _tmp5_; + _tmp6_[1] = NULL; + keys = _tmp6_; + keys_length1 = 2; + _keys_size_ = keys_length1; + _tmp7_ = g_strdup ("90"); + _tmp8_ = g_new0 (gchar*, 2 + 1); + _tmp8_[0] = _tmp7_; + _tmp8_[1] = NULL; + values = _tmp8_; + values_length1 = 2; + _values_size_ = values_length1; + pixbuf_writer_save (writer, image, "jpeg", keys, keys_length1, values, values_length1, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); + keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (icc_profile_data); + _g_object_unref0 (image); + _pixbuf_writer_unref0 (writer); + _g_object_unref0 (stream); + return; + } + values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); + keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); + } else { + gint _tmp9_; + _tmp9_ = g_strcmp0 (type, "png"); + if (_tmp9_ == 0) { + gchar* _tmp10_; + gchar** _tmp11_ = NULL; + gchar** keys; + gint keys_length1; + gint _keys_size_; + gchar* _tmp12_; + gchar** _tmp13_ = NULL; + gchar** values; + gint values_length1; + gint _values_size_; + _tmp10_ = g_strdup ("icc-profile"); + _tmp11_ = g_new0 (gchar*, 2 + 1); + _tmp11_[0] = _tmp10_; + _tmp11_[1] = NULL; + keys = _tmp11_; + keys_length1 = 2; + _keys_size_ = keys_length1; + _tmp12_ = g_strdup (icc_profile_data); + _tmp13_ = g_new0 (gchar*, 2 + 1); + _tmp13_[0] = _tmp12_; + _tmp13_[1] = NULL; + values = _tmp13_; + values_length1 = 2; + _values_size_ = values_length1; + if (icc_profile_data == NULL) { + gchar* _tmp14_; + _tmp14_ = NULL; + _g_free0 (keys[0]); + keys[0] = _tmp14_; + } + pixbuf_writer_save (writer, image, "png", keys, keys_length1, values, values_length1, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); + keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (icc_profile_data); + _g_object_unref0 (image); + _pixbuf_writer_unref0 (writer); + _g_object_unref0 (stream); + return; + } + values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); + keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); + } else { + gint _tmp15_; + _tmp15_ = g_strcmp0 (type, "tiff"); + if (_tmp15_ == 0) { + gchar* _tmp16_; + gchar* _tmp17_; + gchar** _tmp18_ = NULL; + gchar** keys; + gint keys_length1; + gint _keys_size_; + gchar* _tmp19_; + gchar* _tmp20_; + gchar** _tmp21_ = NULL; + gchar** values; + gint values_length1; + gint _values_size_; + _tmp16_ = g_strdup ("compression"); + _tmp17_ = g_strdup ("icc-profile"); + _tmp18_ = g_new0 (gchar*, 3 + 1); + _tmp18_[0] = _tmp16_; + _tmp18_[1] = _tmp17_; + _tmp18_[2] = NULL; + keys = _tmp18_; + keys_length1 = 3; + _keys_size_ = keys_length1; + _tmp19_ = g_strdup ("8"); + _tmp20_ = g_strdup (icc_profile_data); + _tmp21_ = g_new0 (gchar*, 3 + 1); + _tmp21_[0] = _tmp19_; + _tmp21_[1] = _tmp20_; + _tmp21_[2] = NULL; + values = _tmp21_; + values_length1 = 3; + _values_size_ = values_length1; + if (icc_profile_data == NULL) { + gchar* _tmp22_; + _tmp22_ = NULL; + _g_free0 (keys[1]); + keys[1] = _tmp22_; + } + pixbuf_writer_save (writer, image, "tiff", keys, keys_length1, values, values_length1, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); + keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (icc_profile_data); + _g_object_unref0 (image); + _pixbuf_writer_unref0 (writer); + _g_object_unref0 (stream); + return; + } + values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); + keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); + } else { + } + } + } + _g_free0 (icc_profile_data); + _g_object_unref0 (image); + _pixbuf_writer_unref0 (writer); + _g_object_unref0 (stream); +} - /* Extend image */ - rows = page->priv->n_rows; - page->priv->n_rows = rows + page->priv->width / 2; - g_debug("Extending image from %d lines to %d lines", rows, page->priv->n_rows); - page->priv->pixels = g_realloc (page->priv->pixels, page->priv->n_rows * page->priv->rowstride); - *size_changed = TRUE; - } +static void value_page_init (GValue* value) { + value->data[0].v_pointer = NULL; +} - /* Copy in new row */ - memcpy (page->priv->pixels + line_number * page->priv->rowstride, line->data + n * line->data_length, line->data_length); - page->priv->scan_line = line_number; +static void value_page_free_value (GValue* value) { + if (value->data[0].v_pointer) { + page_unref (value->data[0].v_pointer); + } } -void -page_parse_scan_line (Page *page, ScanLine *line) -{ - gint i; - gboolean size_changed = FALSE; +static void value_page_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = page_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} - g_return_if_fail (page != NULL); - for (i = 0; i < line->n_lines; i++) - parse_line (page, line, i, &size_changed); +static gpointer value_page_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} - page->priv->has_data = TRUE; - if (size_changed) - g_signal_emit (page, signals[SIZE_CHANGED], 0); - g_signal_emit (page, signals[SCAN_LINE_CHANGED], 0); - g_signal_emit (page, signals[PIXELS_CHANGED], 0); +static gchar* value_page_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Page* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = page_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; } -void -page_finish (Page *page) -{ - gboolean size_changed = FALSE; +static gchar* value_page_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Page** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = page_ref (value->data[0].v_pointer); + } + return NULL; +} - g_return_if_fail (page != NULL); - /* Trim page */ - if (page->priv->expected_rows < 0 && - page->priv->scan_line != page_get_scan_height (page)) { - gint rows; +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPage* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PAGE), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + - rows = page->priv->n_rows; - page->priv->n_rows = page->priv->scan_line; - page->priv->pixels = g_realloc (page->priv->pixels, page->priv->n_rows * page->priv->rowstride); - g_debug("Trimming page from %d lines to %d lines", rows, page->priv->n_rows); +gpointer value_get_page (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE), NULL); + return value->data[0].v_pointer; +} - size_changed = TRUE; - } - page->priv->scanning = FALSE; - if (size_changed) - g_signal_emit (page, signals[SIZE_CHANGED], 0); - g_signal_emit (page, signals[SCAN_LINE_CHANGED], 0); +void value_set_page (GValue* value, gpointer v_object) { + Page* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + page_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + page_unref (old); + } } -ScanDirection -page_get_scan_direction (Page *page) -{ - g_return_val_if_fail (page != NULL, TOP_TO_BOTTOM); +void value_take_page (GValue* value, gpointer v_object) { + Page* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + page_unref (old); + } +} + - return page->priv->scan_direction; +static void page_class_init (PageClass * klass) { + page_parent_class = g_type_class_peek_parent (klass); + PAGE_CLASS (klass)->finalize = page_finalize; + g_type_class_add_private (klass, sizeof (PagePrivate)); + g_signal_new ("pixels_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("size_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("scan_line_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("scan_direction_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("crop_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } -static void -page_set_scan_direction (Page *page, ScanDirection scan_direction) -{ - gint left_steps, t; - gboolean size_changed = FALSE; - gint width, height; +static void page_instance_init (Page * self) { + self->priv = PAGE_GET_PRIVATE (self); + self->priv->scan_direction = SCAN_DIRECTION_TOP_TO_BOTTOM; + self->ref_count = 1; +} - g_return_if_fail (page != NULL); - if (page->priv->scan_direction == scan_direction) - return; +static void page_finalize (Page* obj) { + Page * self; + self = PAGE (obj); + _g_free0 (self->priv->color_profile); + self->priv->pixels = (g_free (self->priv->pixels), NULL); + _g_free0 (self->priv->crop_name); +} - /* Work out how many times it has been rotated to the left */ - left_steps = scan_direction - page->priv->scan_direction; - if (left_steps < 0) - left_steps += 4; - if (left_steps != 2) - size_changed = TRUE; - - width = page_get_width (page); - height = page_get_height (page); - /* Rotate crop */ - if (page->priv->has_crop) { - switch (left_steps) { - /* 90 degrees counter-clockwise */ - case 1: - t = page->priv->crop_x; - page->priv->crop_x = page->priv->crop_y; - page->priv->crop_y = width - (t + page->priv->crop_width); - t = page->priv->crop_width; - page->priv->crop_width = page->priv->crop_height; - page->priv->crop_height = t; - break; - /* 180 degrees */ - case 2: - page->priv->crop_x = width - (page->priv->crop_x + page->priv->crop_width); - page->priv->crop_y = width - (page->priv->crop_y + page->priv->crop_height); - break; - /* 90 degrees clockwise */ - case 3: - t = page->priv->crop_y; - page->priv->crop_y = page->priv->crop_x; - page->priv->crop_x = height - (t + page->priv->crop_height); - t = page->priv->crop_width; - page->priv->crop_width = page->priv->crop_height; - page->priv->crop_height = t; - break; - } - } +GType page_get_type (void) { + static volatile gsize page_type_id__volatile = 0; + if (g_once_init_enter (&page_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_page_init, value_page_free_value, value_page_copy_value, value_page_peek_pointer, "p", value_page_collect_value, "p", value_page_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) page_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Page), 0, (GInstanceInitFunc) page_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType page_type_id; + page_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Page", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&page_type_id__volatile, page_type_id); + } + return page_type_id__volatile; +} + - page->priv->scan_direction = scan_direction; - if (size_changed) - g_signal_emit (page, signals[SIZE_CHANGED], 0); - g_signal_emit (page, signals[SCAN_DIRECTION_CHANGED], 0); - if (page->priv->has_crop) - g_signal_emit (page, signals[CROP_CHANGED], 0); +gpointer page_ref (gpointer instance) { + Page* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -void -page_rotate_left (Page *page) -{ - ScanDirection scan_direction; +void page_unref (gpointer instance) { + Page* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PAGE_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} - g_return_if_fail (page != NULL); - scan_direction = page_get_scan_direction (page); - if (scan_direction == RIGHT_TO_LEFT) - scan_direction = TOP_TO_BOTTOM; - else - scan_direction++; - page_set_scan_direction (page, scan_direction); +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; } -void -page_rotate_right (Page *page) -{ - ScanDirection scan_direction; +PixbufWriter* pixbuf_writer_construct (GType object_type, GFileOutputStream* stream) { + PixbufWriter* self = NULL; + GFileOutputStream* _tmp0_; + g_return_val_if_fail (stream != NULL, NULL); + self = (PixbufWriter*) g_type_create_instance (object_type); + _tmp0_ = _g_object_ref0 (stream); + _g_object_unref0 (self->stream); + self->stream = _tmp0_; + return self; +} + - scan_direction = page_get_scan_direction (page); - if (scan_direction == TOP_TO_BOTTOM) - scan_direction = RIGHT_TO_LEFT; - else - scan_direction--; - page_set_scan_direction (page, scan_direction); +PixbufWriter* pixbuf_writer_new (GFileOutputStream* stream) { + return pixbuf_writer_construct (TYPE_PIXBUF_WRITER, stream); } -gint -page_get_dpi (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); +static gboolean _pixbuf_writer_write_pixbuf_data_gdk_pixbuf_save_func (guint8* buf, gsize buf_length1, GError** error, gpointer self) { + gboolean result; + result = pixbuf_writer_write_pixbuf_data (self, buf, buf_length1, error); + return result; +} - return page->priv->dpi; + +void pixbuf_writer_save (PixbufWriter* self, GdkPixbuf* image, const gchar* type, gchar** option_keys, int option_keys_length1, gchar** option_values, int option_values_length1, GError** error) { + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (image != NULL); + g_return_if_fail (type != NULL); + gdk_pixbuf_save_to_callbackv (image, _pixbuf_writer_write_pixbuf_data_gdk_pixbuf_save_func, self, type, option_keys, option_values, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } } -gboolean -page_is_landscape (Page *page) -{ - return page_get_width (page) > page_get_height (page); +static gboolean pixbuf_writer_write_pixbuf_data (PixbufWriter* self, guint8* buf, int buf_length1, GError** error) { + gboolean result = FALSE; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, FALSE); + g_output_stream_write_all ((GOutputStream*) self->stream, buf, (gsize) buf_length1, NULL, NULL, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return FALSE; + } + result = TRUE; + return result; } -gint -page_get_width (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); +static void value_pixbuf_writer_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + - if (page->priv->scan_direction == TOP_TO_BOTTOM || page->priv->scan_direction == BOTTOM_TO_TOP) - return page->priv->width; - else - return page->priv->n_rows; +static void value_pixbuf_writer_free_value (GValue* value) { + if (value->data[0].v_pointer) { + pixbuf_writer_unref (value->data[0].v_pointer); + } } -gint -page_get_height (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); +static void value_pixbuf_writer_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = pixbuf_writer_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + - if (page->priv->scan_direction == TOP_TO_BOTTOM || page->priv->scan_direction == BOTTOM_TO_TOP) - return page->priv->n_rows; - else - return page->priv->width; +static gpointer value_pixbuf_writer_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; } -gint -page_get_depth (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); - return page->priv->depth; +static gchar* value_pixbuf_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + PixbufWriter* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = pixbuf_writer_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; } -gint page_get_n_channels (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); - return page->priv->n_channels; +static gchar* value_pixbuf_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + PixbufWriter** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = pixbuf_writer_ref (value->data[0].v_pointer); + } + return NULL; } -gint page_get_rowstride (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); - return page->priv->rowstride; +GParamSpec* param_spec_pixbuf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPixbufWriter* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PIXBUF_WRITER), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); } -gint -page_get_scan_width (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); +gpointer value_get_pixbuf_writer (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PIXBUF_WRITER), NULL); + return value->data[0].v_pointer; +} + - return page->priv->width; +void value_set_pixbuf_writer (GValue* value, gpointer v_object) { + PixbufWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PIXBUF_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PIXBUF_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + pixbuf_writer_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + pixbuf_writer_unref (old); + } } -gint -page_get_scan_height (Page *page) -{ - g_return_val_if_fail (page != NULL, 0); +void value_take_pixbuf_writer (GValue* value, gpointer v_object) { + PixbufWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PIXBUF_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PIXBUF_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + pixbuf_writer_unref (old); + } +} + - return page->priv->n_rows; +static void pixbuf_writer_class_init (PixbufWriterClass * klass) { + pixbuf_writer_parent_class = g_type_class_peek_parent (klass); + PIXBUF_WRITER_CLASS (klass)->finalize = pixbuf_writer_finalize; } -void page_set_color_profile (Page *page, const gchar *color_profile) -{ - g_free (page->priv->color_profile); - page->priv->color_profile = g_strdup (color_profile); +static void pixbuf_writer_instance_init (PixbufWriter * self) { + self->ref_count = 1; } -const gchar *page_get_color_profile (Page *page) -{ - return page->priv->color_profile; +static void pixbuf_writer_finalize (PixbufWriter* obj) { + PixbufWriter * self; + self = PIXBUF_WRITER (obj); + _g_object_unref0 (self->stream); } -void -page_set_no_crop (Page *page) -{ - g_return_if_fail (page != NULL); +GType pixbuf_writer_get_type (void) { + static volatile gsize pixbuf_writer_type_id__volatile = 0; + if (g_once_init_enter (&pixbuf_writer_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_pixbuf_writer_init, value_pixbuf_writer_free_value, value_pixbuf_writer_copy_value, value_pixbuf_writer_peek_pointer, "p", value_pixbuf_writer_collect_value, "p", value_pixbuf_writer_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PixbufWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pixbuf_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PixbufWriter), 0, (GInstanceInitFunc) pixbuf_writer_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType pixbuf_writer_type_id; + pixbuf_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PixbufWriter", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&pixbuf_writer_type_id__volatile, pixbuf_writer_type_id); + } + return pixbuf_writer_type_id__volatile; +} + - if (!page->priv->has_crop) - return; - page->priv->has_crop = FALSE; - g_signal_emit (page, signals[CROP_CHANGED], 0); +gpointer pixbuf_writer_ref (gpointer instance) { + PixbufWriter* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -void -page_set_custom_crop (Page *page, gint width, gint height) -{ - //gint pw, ph; +void pixbuf_writer_unref (gpointer instance) { + PixbufWriter* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PIXBUF_WRITER_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + - g_return_if_fail (page != NULL); - g_return_if_fail (width >= 1); - g_return_if_fail (height >= 1); - - if (!page->priv->crop_name && - page->priv->has_crop && - page->priv->crop_width == width && - page->priv->crop_height == height) - return; - g_free (page->priv->crop_name); - page->priv->crop_name = NULL; - page->priv->has_crop = TRUE; +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} - page->priv->crop_width = width; - page->priv->crop_height = height; - /*pw = page_get_width (page); - ph = page_get_height (page); - if (page->priv->crop_width < pw) - page->priv->crop_x = (pw - page->priv->crop_width) / 2; - else - page->priv->crop_x = 0; - if (page->priv->crop_height < ph) - page->priv->crop_y = (ph - page->priv->crop_height) / 2; - else - page->priv->crop_y = 0;*/ - - g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -void -page_set_named_crop (Page *page, const gchar *name) -{ - struct { - const gchar *name; - /* Width and height in inches */ - gdouble width, height; - } named_crops[] = - { - {"A4", 8.3, 11.7}, - {"A5", 5.8, 8.3}, - {"A6", 4.1, 5.8}, - {"letter", 8.5, 11}, - {"legal", 8.5, 14}, - {"4x6", 4, 6}, - {NULL, 0, 0} - }; - gint i; - gint pw, ph; - double width, height; - - g_return_if_fail (page != NULL); - - for (i = 0; named_crops[i].name && strcmp (name, named_crops[i].name) != 0; i++); - width = named_crops[i].width; - height = named_crops[i].height; - - if (!named_crops[i].name) { - g_warning ("Unknown paper size '%s'", name); - return; - } - - g_free (page->priv->crop_name); - page->priv->crop_name = g_strdup (name); - page->priv->has_crop = TRUE; - - pw = page_get_width (page); - ph = page_get_height (page); - - /* Rotate to match original aspect */ - if (pw > ph) { - double t; - t = width; - width = height; - height = t; - } - - /* Custom crop, make slightly smaller than original */ - page->priv->crop_width = (int) (width * page->priv->dpi + 0.5); - page->priv->crop_height = (int) (height * page->priv->dpi + 0.5); - - if (page->priv->crop_width < pw) - page->priv->crop_x = (pw - page->priv->crop_width) / 2; - else - page->priv->crop_x = 0; - if (page->priv->crop_height < ph) - page->priv->crop_y = (ph - page->priv->crop_height) / 2; - else - page->priv->crop_y = 0; - g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -void -page_move_crop (Page *page, gint x, gint y) -{ - g_return_if_fail (x >= 0); - g_return_if_fail (y >= 0); - g_return_if_fail (x < page_get_width (page)); - g_return_if_fail (y < page_get_height (page)); - - page->priv->crop_x = x; - page->priv->crop_y = y; - g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -void -page_rotate_crop (Page *page) -{ - gint t; - - g_return_if_fail (page != NULL); - - if (!page->priv->has_crop) - return; - - t = page->priv->crop_width; - page->priv->crop_width = page->priv->crop_height; - page->priv->crop_height = t; - - /* Clip custom crops */ - if (!page->priv->crop_name) { - gint w, h; - - w = page_get_width (page); - h = page_get_height (page); - - if (page->priv->crop_x + page->priv->crop_width > w) - page->priv->crop_x = w - page->priv->crop_width; - if (page->priv->crop_x < 0) { - page->priv->crop_x = 0; - page->priv->crop_width = w; - } - if (page->priv->crop_y + page->priv->crop_height > h) - page->priv->crop_y = h - page->priv->crop_height; - if (page->priv->crop_y < 0) { - page->priv->crop_y = 0; - page->priv->crop_height = h; - } - } - - g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -gboolean -page_has_crop (Page *page) -{ - g_return_val_if_fail (page != NULL, FALSE); - return page->priv->has_crop; -} - - -void -page_get_crop (Page *page, gint *x, gint *y, gint *width, gint *height) -{ - g_return_if_fail (page != NULL); - - if (x) - *x = page->priv->crop_x; - if (y) - *y = page->priv->crop_y; - if (width) - *width = page->priv->crop_width; - if (height) - *height = page->priv->crop_height; -} - - -gchar * -page_get_named_crop (Page *page) -{ - g_return_val_if_fail (page != NULL, NULL); - - if (page->priv->crop_name) - return g_strdup (page->priv->crop_name); - else - return NULL; -} - - -const guchar * -page_get_pixels (Page *page) -{ - g_return_val_if_fail (page != NULL, NULL); - return page->priv->pixels; -} - - -// FIXME: Copied from page-view, should be shared code -static guchar -get_sample (const guchar *line, gint x, gint depth, gint n_channels, gint channel) -{ - // FIXME - return 0xFF; -} - - -// FIXME: Copied from page-view, should be shared code -static void -get_pixel (Page *page, gint x, gint y, guchar *pixel) -{ - gint t, depth, n_channels; - const guchar *p, *line; - - switch (page_get_scan_direction (page)) - { - case TOP_TO_BOTTOM: - break; - case BOTTOM_TO_TOP: - x = page_get_scan_width (page) - x - 1; - y = page_get_scan_height (page) - y - 1; - break; - case LEFT_TO_RIGHT: - t = x; - x = page_get_scan_width (page) - y - 1; - y = t; - break; - case RIGHT_TO_LEFT: - t = x; - x = y; - y = page_get_scan_height (page) - t - 1; - break; - } - - depth = page_get_depth (page); - n_channels = page_get_n_channels (page); - line = page_get_pixels (page) + page_get_rowstride (page) * y; - - /* Optimise for 8 bit images */ - if (depth == 8 && n_channels == 3) { - p = line + x * n_channels; - pixel[0] = p[0]; - pixel[1] = p[1]; - pixel[2] = p[2]; - return; - } - else if (depth == 8 && n_channels == 1) { - p = line + x; - pixel[0] = pixel[1] = pixel[2] = p[0]; - return; - } - - /* Optimise for bitmaps */ - else if (depth == 1 && n_channels == 1) { - p = line + (x / 8); - pixel[0] = pixel[1] = pixel[2] = p[0] & (0x80 >> (x % 8)) ? 0x00 : 0xFF; - return; - } - - /* Optimise for 2 bit images */ - else if (depth == 2 && n_channels == 1) { - gint sample; - gint block_shift[4] = { 6, 4, 2, 0 }; - - p = line + (x / 4); - sample = (p[0] >> block_shift[x % 4]) & 0x3; - sample = sample * 255 / 3; - - pixel[0] = pixel[1] = pixel[2] = sample; - return; - } - - /* Use slow method */ - pixel[0] = get_sample (line, x, depth, n_channels, 0); - pixel[0] = get_sample (line, x, depth, n_channels, 1); - pixel[0] = get_sample (line, x, depth, n_channels, 2); -} - - -GdkPixbuf * -page_get_image (Page *page, gboolean apply_crop) -{ - GdkPixbuf *image; - gint x, y, l, r, t, b; - - if (apply_crop && page->priv->has_crop) { - l = page->priv->crop_x; - r = l + page->priv->crop_width; - t = page->priv->crop_y; - b = t + page->priv->crop_height; - - if (l < 0) - l = 0; - if (r > page_get_width (page)) - r = page_get_width (page); - if (t < 0) - t = 0; - if (b > page_get_height (page)) - b = page_get_height (page); - } - else { - l = 0; - r = page_get_width (page); - t = 0; - b = page_get_height (page); - } - - image = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, r - l, b - t); - - for (y = t; y < b; y++) { - guchar *line = gdk_pixbuf_get_pixels (image) + gdk_pixbuf_get_rowstride (image) * (y - t); - for (x = l; x < r; x++) { - guchar *pixel; - - pixel = line + (x - l) * 3; - get_pixel (page, x, y, pixel); - } - } - - return image; -} - - -static gboolean -write_pixbuf_data (const gchar *buf, gsize count, GError **error, GFileOutputStream *stream) -{ - return g_output_stream_write_all (G_OUTPUT_STREAM (stream), buf, count, NULL, NULL, error); -} - - -static gchar * -get_icc_data_encoded (const gchar *icc_profile_filename) -{ - gchar *contents = NULL; - gchar *contents_encode = NULL; - gsize length; - gboolean ret; - GError *error = NULL; - - /* Get binary data */ - ret = g_file_get_contents (icc_profile_filename, &contents, &length, &error); - if (!ret) { - g_warning ("failed to get icc profile data: %s", error->message); - g_error_free (error); - } - else { - /* Encode into base64 */ - contents_encode = g_base64_encode ((const guchar *) contents, length); - } - - g_free (contents); - return contents_encode; -} - - -gboolean -page_save (Page *page, const gchar *type, GFile *file, GError **error) -{ - GFileOutputStream *stream; - GdkPixbuf *image; - gboolean result = FALSE; - gchar *icc_profile_data = NULL; - - stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); - if (!stream) - return FALSE; - - image = page_get_image (page, TRUE); - - if (page->priv->color_profile != NULL) - icc_profile_data = get_icc_data_encoded (page->priv->color_profile); - - if (strcmp (type, "jpeg") == 0) { - /* ICC profile is awaiting review in gtk2+ bugzilla */ - gchar *keys[] = { "quality", /* "icc-profile", */ NULL }; - gchar *values[] = { "90", /* icc_profile_data, */ NULL }; - result = gdk_pixbuf_save_to_callbackv (image, - (GdkPixbufSaveFunc) write_pixbuf_data, stream, - "jpeg", keys, values, error); - } - else if (strcmp (type, "png") == 0) { - gchar *keys[] = { "icc-profile", NULL }; - gchar *values[] = { icc_profile_data, NULL }; - if (icc_profile_data == NULL) - keys[0] = NULL; - result = gdk_pixbuf_save_to_callbackv (image, - (GdkPixbufSaveFunc) write_pixbuf_data, stream, - "png", keys, values, error); - } - else if (strcmp (type, "tiff") == 0) { - gchar *keys[] = { "compression", "icc-profile", NULL }; - gchar *values[] = { "8" /* Deflate compression */, icc_profile_data, NULL }; - if (icc_profile_data == NULL) - keys[1] = NULL; - result = gdk_pixbuf_save_to_callbackv (image, - (GdkPixbufSaveFunc) write_pixbuf_data, stream, - "tiff", keys, values, error); - } - else - result = FALSE; // FIXME: Set GError - - g_free (icc_profile_data); - g_object_unref (image); - g_object_unref (stream); - - return result; -} - - -static void -page_finalize (GObject *object) -{ - Page *page = PAGE (object); - g_free (page->priv->pixels); - G_OBJECT_CLASS (page_parent_class)->finalize (object); -} - - -static void -page_class_init (PageClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = page_finalize; - - signals[PIXELS_CHANGED] = - g_signal_new ("pixels-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageClass, pixels_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[SIZE_CHANGED] = - g_signal_new ("size-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageClass, size_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[SCAN_LINE_CHANGED] = - g_signal_new ("scan-line-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageClass, scan_line_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[SCAN_DIRECTION_CHANGED] = - g_signal_new ("scan-direction-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageClass, scan_direction_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[CROP_CHANGED] = - g_signal_new ("crop-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PageClass, crop_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (PagePrivate)); -} - - -static void -page_init (Page *page) -{ - page->priv = G_TYPE_INSTANCE_GET_PRIVATE (page, PAGE_TYPE, PagePrivate); - page->priv->scan_direction = TOP_TO_BOTTOM; +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); } + + + diff --git a/src/page.h b/src/page.h deleted file mode 100644 index 993029f..0000000 --- a/src/page.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2009 Canonical Ltd. - * Author: Robert Ancell <robert.ancell@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. See http://www.gnu.org/copyleft/gpl.html the full text of the - * license. - */ - -#ifndef _PAGE_H_ -#define _PAGE_H_ - -#include <glib-object.h> -#include <gio/gio.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include "scanner.h" - -G_BEGIN_DECLS - -#define PAGE_TYPE (page_get_type ()) -#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PAGE_TYPE, Page)) - -typedef enum -{ - TOP_TO_BOTTOM, - LEFT_TO_RIGHT, - BOTTOM_TO_TOP, - RIGHT_TO_LEFT -} ScanDirection; - - -typedef struct PagePrivate PagePrivate; - -typedef struct -{ - GObject parent_instance; - PagePrivate *priv; -} Page; - -typedef struct -{ - GObjectClass parent_class; - - void (*pixels_changed) (Page *page); - void (*size_changed) (Page *page); - void (*scan_line_changed) (Page *page); - void (*scan_direction_changed) (Page *page); - void (*crop_changed) (Page *page); -} PageClass; - - -GType page_get_type (void); - -Page *page_new (gint width, gint height, gint dpi, ScanDirection scan_direction); - -void page_set_page_info (Page *page, ScanPageInfo *info); - -gint page_get_dpi (Page *page); - -gint page_get_width (Page *page); - -gint page_get_height (Page *page); - -gint page_get_depth (Page *page); - -gint page_get_n_channels (Page *page); - -gint page_get_rowstride (Page *page); - -const guchar *page_get_pixels (Page *page); - -guchar *page_get_pixel (Page *page, gint x, gint y); - -gboolean page_is_landscape (Page *page); - -gint page_get_scan_width (Page *page); - -gint page_get_scan_height (Page *page); - -void page_set_color_profile (Page *page, const gchar *color_profile); - -const gchar *page_get_color_profile (Page *page); - -void page_start (Page *page); - -gboolean page_is_scanning (Page *page); - -gboolean page_has_data (Page *page); - -gboolean page_is_color (Page *page); - -gint page_get_scan_line (Page *page); - -void page_parse_scan_line (Page *page, ScanLine *line); - -void page_finish (Page *page); - -ScanDirection page_get_scan_direction (Page *page); - -void page_rotate_left (Page *page); - -void page_rotate_right (Page *page); - -void page_set_no_crop (Page *page); - -void page_set_custom_crop (Page *page, gint width, gint height); - -void page_set_named_crop (Page *page, const gchar *name); - -void page_move_crop (Page *page, gint x, gint y); - -void page_rotate_crop (Page *page); - -gboolean page_has_crop (Page *page); - -void page_get_crop (Page *page, gint *x, gint *y, gint *width, gint *height); - -gchar *page_get_named_crop (Page *page); - -GdkPixbuf *page_get_image (Page *page, gboolean apply_crop); - -gboolean page_save (Page *page, const gchar *type, GFile *file, GError **error); - -#endif /* _PAGE_H_ */ diff --git a/src/page.vala b/src/page.vala new file mode 100644 index 0000000..ef7ddb6 --- /dev/null +++ b/src/page.vala @@ -0,0 +1,735 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public enum ScanDirection +{ + TOP_TO_BOTTOM, + LEFT_TO_RIGHT, + BOTTOM_TO_TOP, + RIGHT_TO_LEFT +} + +public class Page +{ + /* Resolution of page */ + private int dpi; + + /* Number of rows in this page or -1 if currently unknown */ + private int expected_rows; + + /* Bit depth */ + private int depth; + + /* Color profile */ + private string? color_profile; + + /* Scanned image data */ + private int width; + private int n_rows; + private int rowstride; + private int n_channels; + private uchar[] pixels; + + /* Page is getting data */ + private bool scanning; + + /* true if have some page data */ + private bool has_data_; + + /* Expected next scan row */ + private int scan_line; + + /* Rotation of scanned data */ + private ScanDirection scan_direction = ScanDirection.TOP_TO_BOTTOM; + + /* Crop */ + private bool has_crop_; + private string? crop_name; + private int crop_x; + private int crop_y; + private int crop_width; + private int crop_height; + + public signal void pixels_changed (); + public signal void size_changed (); + public signal void scan_line_changed (); + public signal void scan_direction_changed (); + public signal void crop_changed (); + + public Page (int width, int height, int dpi, ScanDirection scan_direction) + { + if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) + { + this.width = width; + n_rows = height; + } + else + { + this.width = height; + n_rows = width; + } + this.dpi = dpi; + this.scan_direction = scan_direction; + } + + public void set_page_info (ScanPageInfo info) + { + expected_rows = info.height; + dpi = (int) info.dpi; + + /* Create a white page */ + width = info.width; + n_rows = info.height; + /* Variable height, try 50% of the width for now */ + if (n_rows < 0) + n_rows = width / 2; + depth = info.depth; + n_channels = info.n_channels; + rowstride = (width * depth * n_channels + 7) / 8; + pixels.resize (n_rows * rowstride); + return_if_fail (pixels != null); + + /* Fill with white */ + if (depth == 1) + Memory.set (pixels, 0x00, n_rows * rowstride); + else + Memory.set (pixels, 0xFF, n_rows * rowstride); + + size_changed (); + pixels_changed (); + } + + public void start () + { + scanning = true; + scan_line_changed (); + } + + public bool is_scanning () + { + return scanning; + } + + public bool has_data () + { + return has_data_; + } + + public bool is_color () + { + return n_channels > 1; + } + + public int get_scan_line () + { + return scan_line; + } + + private void parse_line (ScanLine line, int n, out bool size_changed) + { + int line_number; + + line_number = line.number + n; + + /* Extend image if necessary */ + size_changed = false; + while (line_number >= get_scan_height ()) + { + int rows; + + /* Extend image */ + rows = n_rows; + n_rows = rows + width / 2; + debug ("Extending image from %d lines to %d lines", rows, n_rows); + pixels.resize (n_rows * rowstride); + + size_changed = true; + } + + /* Copy in new row */ + var offset = line_number * rowstride; + var line_offset = n * line.data_length; + for (var i = 0; i < line.data_length; i++) + pixels[offset+i] = line.data[line_offset+i]; + + scan_line = line_number; + } + + public void parse_scan_line (ScanLine line) + { + bool size_has_changed = false; + for (var i = 0; i < line.n_lines; i++) + parse_line (line, i, out size_has_changed); + + has_data_ = true; + + if (size_has_changed) + size_changed (); + scan_line_changed (); + pixels_changed (); + } + + public void finish () + { + bool size_has_changed = false; + + /* Trim page */ + if (expected_rows < 0 && + scan_line != get_scan_height ()) + { + int rows; + + rows = n_rows; + n_rows = scan_line; + pixels.resize (n_rows * rowstride); + debug ("Trimming page from %d lines to %d lines", rows, n_rows); + + size_has_changed = true; + } + scanning = false; + + if (size_has_changed) + size_changed (); + scan_line_changed (); + } + + public ScanDirection get_scan_direction () + { + return scan_direction; + } + + private void set_scan_direction (ScanDirection direction) + { + int left_steps, t; + bool size_has_changed = false; + int width, height; + + if (scan_direction == direction) + return; + + /* Work out how many times it has been rotated to the left */ + left_steps = direction - scan_direction; + if (left_steps < 0) + left_steps += 4; + if (left_steps != 2) + size_has_changed = true; + + width = get_width (); + height = get_height (); + + /* Rotate crop */ + if (has_crop_) + { + switch (left_steps) + { + /* 90 degrees counter-clockwise */ + case 1: + t = crop_x; + crop_x = crop_y; + crop_y = width - (t + crop_width); + t = crop_width; + crop_width = crop_height; + crop_height = t; + break; + /* 180 degrees */ + case 2: + crop_x = width - (crop_x + crop_width); + crop_y = width - (crop_y + crop_height); + break; + /* 90 degrees clockwise */ + case 3: + t = crop_y; + crop_y = crop_x; + crop_x = height - (t + crop_height); + t = crop_width; + crop_width = crop_height; + crop_height = t; + break; + } + } + + scan_direction = direction; + if (size_has_changed) + size_changed (); + scan_direction_changed (); + if (has_crop_) + crop_changed (); + } + + public void rotate_left () + { + var direction = scan_direction; + switch (direction) + { + case ScanDirection.TOP_TO_BOTTOM: + direction = ScanDirection.LEFT_TO_RIGHT; + break; + case ScanDirection.LEFT_TO_RIGHT: + direction = ScanDirection.BOTTOM_TO_TOP; + break; + case ScanDirection.BOTTOM_TO_TOP: + direction = ScanDirection.RIGHT_TO_LEFT; + break; + case ScanDirection.RIGHT_TO_LEFT: + direction = ScanDirection.TOP_TO_BOTTOM; + break; + } + set_scan_direction (direction); + } + + public void rotate_right () + { + var direction = scan_direction; + switch (direction) + { + case ScanDirection.TOP_TO_BOTTOM: + direction = ScanDirection.RIGHT_TO_LEFT; + break; + case ScanDirection.LEFT_TO_RIGHT: + direction = ScanDirection.TOP_TO_BOTTOM; + break; + case ScanDirection.BOTTOM_TO_TOP: + direction = ScanDirection.LEFT_TO_RIGHT; + break; + case ScanDirection.RIGHT_TO_LEFT: + direction = ScanDirection.BOTTOM_TO_TOP; + break; + } + set_scan_direction (direction); + } + + public int get_dpi () + { + return dpi; + } + + public bool is_landscape () + { + return get_width () > get_height (); + } + + public int get_width () + { + if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) + return width; + else + return n_rows; + } + + public int get_height () + { + if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) + return n_rows; + else + return width; + } + + public int get_depth () + { + return depth; + } + + public int get_n_channels () + { + return n_channels; + } + + public int get_rowstride () + { + return rowstride; + } + + public int get_scan_width () + { + return width; + } + + public int get_scan_height () + { + return n_rows; + } + + public void set_color_profile (string? color_profile) + { + this.color_profile = color_profile; + } + + public string get_color_profile () + { + return color_profile; + } + + public void set_no_crop () + { + if (!has_crop_) + return; + has_crop_ = false; + crop_changed (); + } + + public void set_custom_crop (int width, int height) + { + //int pw, ph; + + return_if_fail (width >= 1); + return_if_fail (height >= 1); + + if (crop_name == null && has_crop_ && crop_width == width && crop_height == height) + return; + crop_name = null; + has_crop_ = true; + + crop_width = width; + crop_height = height; + + /*pw = get_width (); + ph = get_height (); + if (crop_width < pw) + crop_x = (pw - crop_width) / 2; + else + crop_x = 0; + if (crop_height < ph) + crop_y = (ph - crop_height) / 2; + else + crop_y = 0;*/ + + crop_changed (); + } + + public void set_named_crop (string name) + { + double width, height; + switch (name) + { + case "A4": + width = 8.3; + height = 11.7; + break; + case "A5": + width = 5.8; + height = 8.3; + break; + case "A6": + width = 4.1; + height = 5.8; + break; + case "letter": + width = 8.5; + height = 11; + break; + case "legal": + width = 8.5; + height = 14; + break; + case "4x6": + width = 4; + height = 6; + break; + default: + warning ("Unknown paper size '%s'", name); + return; + } + + crop_name = name; + has_crop_ = true; + + var pw = get_width (); + var ph = get_height (); + + /* Rotate to match original aspect */ + if (pw > ph) + { + double t; + t = width; + width = height; + height = t; + } + + /* Custom crop, make slightly smaller than original */ + crop_width = (int) (width * dpi + 0.5); + crop_height = (int) (height * dpi + 0.5); + + if (crop_width < pw) + crop_x = (pw - crop_width) / 2; + else + crop_x = 0; + if (crop_height < ph) + crop_y = (ph - crop_height) / 2; + else + crop_y = 0; + crop_changed (); + } + + public void move_crop (int x, int y) + { + return_if_fail (x >= 0); + return_if_fail (y >= 0); + return_if_fail (x < get_width ()); + return_if_fail (y < get_height ()); + + crop_x = x; + crop_y = y; + crop_changed (); + } + + public void rotate_crop () + { + int t; + + if (!has_crop_) + return; + + t = crop_width; + crop_width = crop_height; + crop_height = t; + + /* Clip custom crops */ + if (crop_name == null) + { + int w, h; + + w = get_width (); + h = get_height (); + + if (crop_x + crop_width > w) + crop_x = w - crop_width; + if (crop_x < 0) + { + crop_x = 0; + crop_width = w; + } + if (crop_y + crop_height > h) + crop_y = h - crop_height; + if (crop_y < 0) + { + crop_y = 0; + crop_height = h; + } + } + + crop_changed (); + } + + public bool has_crop () + { + return has_crop_; + } + + public void get_crop (out int x, out int y, out int width, out int height) + { + x = crop_x; + y = crop_y; + width = crop_width; + height = crop_height; + } + + public string get_named_crop () + { + return crop_name; + } + + public unowned uchar[] get_pixels () + { + return pixels; + } + + // FIXME: Copied from page-view, should be shared code + private uchar get_sample (uchar[] pixels, int offset, int x, int depth, int n_channels, int channel) + { + // FIXME + return 0xFF; + } + + // FIXME: Copied from page-view, should be shared code + private void get_pixel (int x, int y, uchar[] pixel, int offset) + { + switch (get_scan_direction ()) + { + case ScanDirection.TOP_TO_BOTTOM: + break; + case ScanDirection.BOTTOM_TO_TOP: + x = get_scan_width () - x - 1; + y = get_scan_height () - y - 1; + break; + case ScanDirection.LEFT_TO_RIGHT: + var t = x; + x = get_scan_width () - y - 1; + y = t; + break; + case ScanDirection.RIGHT_TO_LEFT: + var t = x; + x = y; + y = get_scan_height () - t - 1; + break; + } + + var depth = get_depth (); + var n_channels = get_n_channels (); + var line_offset = get_rowstride () * y; + + /* Optimise for 8 bit images */ + if (depth == 8 && n_channels == 3) + { + var o = line_offset + x * n_channels; + pixel[offset+0] = pixels[o]; + pixel[offset+1] = pixels[o+1]; + pixel[offset+2] = pixels[o+2]; + return; + } + else if (depth == 8 && n_channels == 1) + { + var p = pixels[line_offset + x]; + pixel[offset+0] = pixel[offset+1] = pixel[offset+2] = p; + return; + } + + /* Optimise for bitmaps */ + else if (depth == 1 && n_channels == 1) + { + var p = pixels[line_offset + (x / 8)]; + pixel[offset+0] = pixel[offset+1] = pixel[offset+2] = (p & (0x80 >> (x % 8))) != 0 ? 0x00 : 0xFF; + return; + } + + /* Optimise for 2 bit images */ + else if (depth == 2 && n_channels == 1) + { + int block_shift[4] = { 6, 4, 2, 0 }; + + var p = pixels[line_offset + (x / 4)]; + var sample = (p >> block_shift[x % 4]) & 0x3; + sample = sample * 255 / 3; + + pixel[offset+0] = pixel[offset+1] = pixel[offset+2] = (uchar) sample; + return; + } + + /* Use slow method */ + pixel[offset+0] = get_sample (pixels, line_offset, x, depth, n_channels, 0); + pixel[offset+1] = get_sample (pixels, line_offset, x, depth, n_channels, 1); + pixel[offset+2] = get_sample (pixels, line_offset, x, depth, n_channels, 2); + } + + public Gdk.Pixbuf get_image (bool apply_crop) + { + int l, r, t, b; + if (apply_crop && has_crop_) + { + l = crop_x; + r = l + crop_width; + t = crop_y; + b = t + crop_height; + + if (l < 0) + l = 0; + if (r > get_width ()) + r = get_width (); + if (t < 0) + t = 0; + if (b > get_height ()) + b = get_height (); + } + else + { + l = 0; + r = get_width (); + t = 0; + b = get_height (); + } + + var image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, r - l, b - t); + unowned uint8[] image_pixels = image.get_pixels (); + for (var y = t; y < b; y++) + { + var offset = image.get_rowstride () * (y - t); + for (var x = l; x < r; x++) + get_pixel (x, y, image_pixels, offset + (x - l) * 3); + } + + return image; + } + + private string? get_icc_data_encoded (string icc_profile_filename) + { + /* Get binary data */ + string contents; + try + { + FileUtils.get_contents (icc_profile_filename, out contents); + } + catch (Error e) + { + warning ("failed to get icc profile data: %s", e.message); + return null; + } + + /* Encode into base64 */ + return Base64.encode ((uchar[]) contents.to_utf8 ()); + } + + public void save (string type, File file) throws Error + { + var stream = file.replace (null, false, FileCreateFlags.NONE, null); + var writer = new PixbufWriter (stream); + var image = get_image (true); + + string? icc_profile_data = null; + if (color_profile != null) + icc_profile_data = get_icc_data_encoded (color_profile); + + if (strcmp (type, "jpeg") == 0) + { + /* ICC profile is awaiting review in gtk2+ bugzilla */ + string[] keys = { "quality", /* "icc-profile", */ null }; + string[] values = { "90", /* icc_profile_data, */ null }; + writer.save (image, "jpeg", keys, values); + } + else if (strcmp (type, "png") == 0) + { + string[] keys = { "icc-profile", null }; + string[] values = { icc_profile_data, null }; + if (icc_profile_data == null) + keys[0] = null; + writer.save (image, "png", keys, values); + } + else if (strcmp (type, "tiff") == 0) + { + string[] keys = { "compression", "icc-profile", null }; + string[] values = { "8" /* Deflate compression */, icc_profile_data, null }; + if (icc_profile_data == null) + keys[1] = null; + writer.save (image, "tiff", keys, values); + } + else + ; // FIXME: Throw Error + } +} + +public class PixbufWriter +{ + public FileOutputStream stream; + + public PixbufWriter (FileOutputStream stream) + { + this.stream = stream; + } + + public void save (Gdk.Pixbuf image, string type, string[] option_keys, string[] option_values) throws Error + { + image.save_to_callbackv (write_pixbuf_data, type, option_keys, option_values); + } + + private bool write_pixbuf_data (uint8[] buf) throws Error + { + stream.write_all (buf, null, null); + return true; + } +} diff --git a/src/sane.vapi b/src/sane.vapi new file mode 100644 index 0000000..ae69940 --- /dev/null +++ b/src/sane.vapi @@ -0,0 +1,757 @@ +[CCode (cprefix = "SANE_", lower_case_cprefix = "sane_", cheader_filename = "sane/sane.h")] +namespace Sane { + [SimpleType] + [BooleanType] + public struct Bool + { + } + + [SimpleType] + [IntegerType] + public struct Int + { + } + + [SimpleType] + [IntegerType] + public struct Fixed + { + } + + [SimpleType] + [IntegerType] + public struct Word + { + } + + [CCode (ref_function = "", unref_function = "")] + public class Device + { + public string name; + public string vendor; + public string model; + public string type; + } + + public enum Status + { + GOOD, + UNSUPPORTED, + CANCELLED, + DEVICE_BUSY, + INVAL, + EOF, + JAMMED, + NO_DOCS, + COVER_OPEN, + IO_ERROR, + NO_MEM, + ACCESS_DENIED + } + + public static string status_to_string (Status status) + { + switch (status) + { + case Status.GOOD: + return "SANE_STATUS_GOOD"; + case Status.UNSUPPORTED: + return "SANE_STATUS_UNSUPPORTED"; + case Status.CANCELLED: + return "SANE_STATUS_CANCELLED"; + case Status.DEVICE_BUSY: + return "SANE_STATUS_DEVICE_BUSY"; + case Status.INVAL: + return "SANE_STATUS_INVAL"; + case Status.EOF: + return "SANE_STATUS_EOF"; + case Status.JAMMED: + return "SANE_STATUS_JAMMED"; + case Status.NO_DOCS: + return "SANE_STATUS_NO_DOCS"; + case Status.COVER_OPEN: + return "SANE_STATUS_COVER_OPEN"; + case Status.IO_ERROR: + return "SANE_STATUS_IO_ERROR"; + case Status.NO_MEM: + return "SANE_STATUS_NO_MEM"; + case Status.ACCESS_DENIED: + return "SANE_STATUS_ACCESS_DENIED"; + default: + return "SANE_STATUS(%d)".printf (status); + } + } + + public enum Action + { + GET_VALUE, + SET_VALUE, + SET_AUTO + } + + public enum Frame + { + GRAY, + RGB, + RED, + GREEN, + BLUE + } + + public static string frame_to_string (Frame frame) + { + switch (frame) + { + case Frame.GRAY: + return "SANE_FRAME_GRAY"; + case Frame.RGB: + return "SANE_FRAME_RGB"; + case Frame.RED: + return "SANE_FRAME_RED"; + case Frame.GREEN: + return "SANE_FRAME_GREEN"; + case Frame.BLUE: + return "SANE_FRAME_BLUE"; + default: + return "SANE_FRAME(%d)".printf (frame); + } + } + + public struct Parameters + { + Frame format; + bool last_frame; + int bytes_per_line; + int pixels_per_line; + int lines; + int depth; + } + + [CCode (cname = "SANE_MAX_USERNAME_LEN")] + public int MAX_USERNAME_LEN; + + [CCode (cname = "SANE_MAX_USERNAME_LEN")] + public int MAX_PASSWORD_LEN; + + [CCode (cname = "SANE_Value_Type", cprefix = "SANE_TYPE_")] + public enum ValueType + { + BOOL, + INT, + FIXED, + STRING, + BUTTON, + GROUP + } + + public enum Unit + { + NONE, + PIXEL, + BIT, + MM, + DPI, + PERCENT, + MICROSECOND + } + + [CCode (cname = "const SANE_Constraint_Type", cprefix = "SANE_CONSTRAINT_")] + public enum ConstraintType + { + NONE, + RANGE, + WORD_LIST, + STRING_LIST + } + + public class Range + { + public Word min; + public Word max; + public Word quant; + } + + [CCode (cprefix = "SANE_CAP_")] + public enum Capability + { + SOFT_SELECT, + HARD_SELECT, + SOFT_DETECT, + EMULATED, + AUTOMATIC, + INACTIVE, + ADVANCED + } + + [CCode (cname = "const SANE_Option_Descriptor", ref_function = "", unref_function = "")] + public class OptionDescriptor + { + public string name; + public string title; + public string desc; + public ValueType type; + public Unit unit; + public Int size; + public Int cap; + + public ConstraintType constraint_type; + public struct _Constraint + { + [CCode (array_length = false, null_terminated = true)] + public string[] string_list; + public Word[] word_list; + public Range range; + } + public _Constraint constraint; + } + + [CCode (type = "Int", cprefix = "SANE_INFO_")] + public enum Info + { + INEXACT, + RELOAD_OPTIONS, + RELOAD_PARAMS + } + + [SimpleType] + public struct Handle + { + } + + [CCode (has_target = false)] + public delegate void AuthCallback (string resource, [CCode (array_length = false)] char[] username, [CCode (array_length = false)] char[] password); + + [CCode (cname = "SANE_VERSION_MAJOR")] + public int VERSION_MAJOR (Int code); + [CCode (cname = "SANE_VERSION_MINOR")] + public int VERSION_MINOR (Int code); + [CCode (cname = "SANE_VERSION_BUILD")] + public int VERSION_BUILD (Int code); + + [CCode (cname = "SANE_FIX")] + public Fixed FIX (double d); + [CCode (cname = "SANE_UNFIX")] + public double UNFIX (Fixed w); + + [CCode (cname = "SANE_I18N")] + public unowned string I18N (string value); + + public Status init (out Int version_code, AuthCallback callback); + public void exit (); + public Status get_devices ([CCode (array_length = false, null_terminated = true)] out unowned Device[] device_list, bool local_only); + public unowned string strstatus (Status status); + public Status open (string devicename, out Handle handle); + public void close (Handle handle); + public unowned OptionDescriptor? get_option_descriptor (Handle handle, Int option); + public Status control_option (Handle handle, Int option, Action action, void *value, out Info? info = null); + public Status get_parameters (Handle handle, out Parameters params); + public Status start (Handle handle); + public Status read (Handle handle, uint8* data, Int max_length, out Int length); + public void cancel (Handle handle); + public Status set_io_mode (Handle handle, bool non_blocking); + public Status get_select_fd (Handle handle, out int fd); + + [CCode (cname = "SANE_NAME_STANDARD", cheader_filename = "sane/saneopts.h")] + public static string NAME_STANDARD; + [CCode (cname = "SANE_NAME_GEOMETRY", cheader_filename = "sane/saneopts.h")] + public static string NAME_GEOMETRY; + [CCode (cname = "SANE_NAME_ENHANCEMENT", cheader_filename = "sane/saneopts.h")] + public static string NAME_ENHANCEMENT; + [CCode (cname = "SANE_NAME_ADVANCED", cheader_filename = "sane/saneopts.h")] + public static string NAME_ADVANCED; + [CCode (cname = "SANE_NAME_SENSORS", cheader_filename = "sane/saneopts.h")] + public static string NAME_SENSORS; + [CCode (cname = "SANE_NAME_PREVIEW", cheader_filename = "sane/saneopts.h")] + public static string NAME_PREVIEW; + [CCode (cname = "SANE_NAME_GRAY_PREVIEW", cheader_filename = "sane/saneopts.h")] + public static string NAME_GRAY_PREVIEW; + [CCode (cname = "SANE_NAME_BIT_DEPTH", cheader_filename = "sane/saneopts.h")] + public static string NAME_BIT_DEPTH; + [CCode (cname = "SANE_NAME_SCAN_MODE", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_MODE; + [CCode (cname = "SANE_NAME_SCAN_SPEED", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_SPEED; + [CCode (cname = "SANE_NAME_SCAN_SOURCE", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_SOURCE; + [CCode (cname = "SANE_NAME_BACKTRACK", cheader_filename = "sane/saneopts.h")] + public static string NAME_BACKTRACK; + [CCode (cname = "SANE_NAME_SCAN_TL_X", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_TL_X; + [CCode (cname = "SANE_NAME_SCAN_TL_Y", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_TL_Y; + [CCode (cname = "SANE_NAME_SCAN_BR_X", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_BR_X; + [CCode (cname = "SANE_NAME_SCAN_BR_Y", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_BR_Y; + [CCode (cname = "SANE_NAME_SCAN_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_RESOLUTION; + [CCode (cname = "SANE_NAME_SCAN_X_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_X_RESOLUTION; + [CCode (cname = "SANE_NAME_SCAN_Y_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_Y_RESOLUTION; + [CCode (cname = "SANE_NAME_PAGE_WIDTH", cheader_filename = "sane/saneopts.h")] + public static string NAME_PAGE_WIDTH; + [CCode (cname = "SANE_NAME_PAGE_HEIGHT", cheader_filename = "sane/saneopts.h")] + public static string NAME_PAGE_HEIGHT; + [CCode (cname = "SANE_NAME_CUSTOM_GAMMA", cheader_filename = "sane/saneopts.h")] + public static string NAME_CUSTOM_GAMMA; + [CCode (cname = "SANE_NAME_GAMMA_VECTOR", cheader_filename = "sane/saneopts.h")] + public static string NAME_GAMMA_VECTOR; + [CCode (cname = "SANE_NAME_GAMMA_VECTOR_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_GAMMA_VECTOR_R; + [CCode (cname = "SANE_NAME_GAMMA_VECTOR_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_GAMMA_VECTOR_G; + [CCode (cname = "SANE_NAME_GAMMA_VECTOR_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_GAMMA_VECTOR_B; + [CCode (cname = "SANE_NAME_BRIGHTNESS", cheader_filename = "sane/saneopts.h")] + public static string NAME_BRIGHTNESS; + [CCode (cname = "SANE_NAME_CONTRAST", cheader_filename = "sane/saneopts.h")] + public static string NAME_CONTRAST; + [CCode (cname = "SANE_NAME_GRAIN_SIZE", cheader_filename = "sane/saneopts.h")] + public static string NAME_GRAIN_SIZE; + [CCode (cname = "SANE_NAME_HALFTONE", cheader_filename = "sane/saneopts.h")] + public static string NAME_HALFTONE; + [CCode (cname = "SANE_NAME_BLACK_LEVEL", cheader_filename = "sane/saneopts.h")] + public static string NAME_BLACK_LEVEL; + [CCode (cname = "SANE_NAME_WHITE_LEVEL", cheader_filename = "sane/saneopts.h")] + public static string NAME_WHITE_LEVEL; + [CCode (cname = "SANE_NAME_WHITE_LEVEL_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_WHITE_LEVEL_R; + [CCode (cname = "SANE_NAME_WHITE_LEVEL_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_WHITE_LEVEL_G; + [CCode (cname = "SANE_NAME_WHITE_LEVEL_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_WHITE_LEVEL_B; + [CCode (cname = "SANE_NAME_SHADOW", cheader_filename = "sane/saneopts.h")] + public static string NAME_SHADOW; + [CCode (cname = "SANE_NAME_SHADOW_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_SHADOW_R; + [CCode (cname = "SANE_NAME_SHADOW_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_SHADOW_G; + [CCode (cname = "SANE_NAME_SHADOW_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_SHADOW_B; + [CCode (cname = "SANE_NAME_HIGHLIGHT", cheader_filename = "sane/saneopts.h")] + public static string NAME_HIGHLIGHT; + [CCode (cname = "SANE_NAME_HIGHLIGHT_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_HIGHLIGHT_R; + [CCode (cname = "SANE_NAME_HIGHLIGHT_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_HIGHLIGHT_G; + [CCode (cname = "SANE_NAME_HIGHLIGHT_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_HIGHLIGHT_B; + [CCode (cname = "SANE_NAME_HUE", cheader_filename = "sane/saneopts.h")] + public static string NAME_HUE; + [CCode (cname = "SANE_NAME_SATURATION", cheader_filename = "sane/saneopts.h")] + public static string NAME_SATURATION; + [CCode (cname = "SANE_NAME_FILE", cheader_filename = "sane/saneopts.h")] + public static string NAME_FILE; + [CCode (cname = "SANE_NAME_HALFTONE_DIMENSION", cheader_filename = "sane/saneopts.h")] + public static string NAME_HALFTONE_DIMENSION; + [CCode (cname = "SANE_NAME_HALFTONE_PATTERN", cheader_filename = "sane/saneopts.h")] + public static string NAME_HALFTONE_PATTERN; + [CCode (cname = "SANE_NAME_RESOLUTION_BIND", cheader_filename = "sane/saneopts.h")] + public static string NAME_RESOLUTION_BIND; + [CCode (cname = "SANE_NAME_NEGATIVE", cheader_filename = "sane/saneopts.h")] + public static string NAME_NEGATIVE; + [CCode (cname = "SANE_NAME_QUALITY_CAL", cheader_filename = "sane/saneopts.h")] + public static string NAME_QUALITY_CAL; + [CCode (cname = "SANE_NAME_DOR", cheader_filename = "sane/saneopts.h")] + public static string NAME_DOR; + [CCode (cname = "SANE_NAME_RGB_BIND", cheader_filename = "sane/saneopts.h")] + public static string NAME_RGB_BIND; + [CCode (cname = "SANE_NAME_THRESHOLD", cheader_filename = "sane/saneopts.h")] + public static string NAME_THRESHOLD; + [CCode (cname = "SANE_NAME_ANALOG_GAMMA", cheader_filename = "sane/saneopts.h")] + public static string NAME_ANALOG_GAMMA; + [CCode (cname = "SANE_NAME_ANALOG_GAMMA_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_ANALOG_GAMMA_R; + [CCode (cname = "SANE_NAME_ANALOG_GAMMA_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_ANALOG_GAMMA_G; + [CCode (cname = "SANE_NAME_ANALOG_GAMMA_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_ANALOG_GAMMA_B; + [CCode (cname = "SANE_NAME_ANALOG_GAMMA_BIND", cheader_filename = "sane/saneopts.h")] + public static string NAME_ANALOG_GAMMA_BIND; + [CCode (cname = "SANE_NAME_WARMUP", cheader_filename = "sane/saneopts.h")] + public static string NAME_WARMUP; + [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME", cheader_filename = "sane/saneopts.h")] + public static string NAME_CAL_EXPOS_TIME; + [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_CAL_EXPOS_TIME_R; + [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_CAL_EXPOS_TIME_G; + [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_CAL_EXPOS_TIME_B; + [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_EXPOS_TIME; + [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_EXPOS_TIME_R; + [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_EXPOS_TIME_G; + [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_EXPOS_TIME_B; + [CCode (cname = "SANE_NAME_SELECT_EXPOSURE_TIME", cheader_filename = "sane/saneopts.h")] + public static string NAME_SELECT_EXPOSURE_TIME; + [CCode (cname = "SANE_NAME_CAL_LAMP_DEN", cheader_filename = "sane/saneopts.h")] + public static string NAME_CAL_LAMP_DEN; + [CCode (cname = "SANE_NAME_SCAN_LAMP_DEN", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN_LAMP_DEN; + [CCode (cname = "SANE_NAME_SELECT_LAMP_DENSITY", cheader_filename = "sane/saneopts.h")] + public static string NAME_SELECT_LAMP_DENSITY; + [CCode (cname = "SANE_NAME_LAMP_OFF_AT_EXIT", cheader_filename = "sane/saneopts.h")] + public static string NAME_LAMP_OFF_AT_EXIT; + [CCode (cname = "SANE_NAME_SCAN", cheader_filename = "sane/saneopts.h")] + public static string NAME_SCAN; + [CCode (cname = "SANE_NAME_EMAIL", cheader_filename = "sane/saneopts.h")] + public static string NAME_EMAIL; + [CCode (cname = "SANE_NAME_FAX", cheader_filename = "sane/saneopts.h")] + public static string NAME_FAX; + [CCode (cname = "SANE_NAME_COPY", cheader_filename = "sane/saneopts.h")] + public static string NAME_COPY; + [CCode (cname = "SANE_NAME_PDF", cheader_filename = "sane/saneopts.h")] + public static string NAME_PDF; + [CCode (cname = "SANE_NAME_CANCEL", cheader_filename = "sane/saneopts.h")] + public static string NAME_CANCEL; + [CCode (cname = "SANE_NAME_PAGE_LOADED", cheader_filename = "sane/saneopts.h")] + public static string NAME_PAGE_LOADED; + [CCode (cname = "SANE_NAME_COVER_OPEN", cheader_filename = "sane/saneopts.h")] + public static string NAME_COVER_OPEN; + [CCode (cname = "SANE_TITLE_NUM_OPTIONS", cheader_filename = "sane/saneopts.h")] + public static string TITLE_NUM_OPTIONS; + [CCode (cname = "SANE_TITLE_STANDARD", cheader_filename = "sane/saneopts.h")] + public static string TITLE_STANDARD; + [CCode (cname = "SANE_TITLE_GEOMETRY", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GEOMETRY; + [CCode (cname = "SANE_TITLE_ENHANCEMENT", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ENHANCEMENT; + [CCode (cname = "SANE_TITLE_ADVANCED", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ADVANCED; + [CCode (cname = "SANE_TITLE_SENSORS", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SENSORS; + [CCode (cname = "SANE_TITLE_PREVIEW", cheader_filename = "sane/saneopts.h")] + public static string TITLE_PREVIEW; + [CCode (cname = "SANE_TITLE_GRAY_PREVIEW", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GRAY_PREVIEW; + [CCode (cname = "SANE_TITLE_BIT_DEPTH", cheader_filename = "sane/saneopts.h")] + public static string TITLE_BIT_DEPTH; + [CCode (cname = "SANE_TITLE_SCAN_MODE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_MODE; + [CCode (cname = "SANE_TITLE_SCAN_SPEED", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_SPEED; + [CCode (cname = "SANE_TITLE_SCAN_SOURCE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_SOURCE; + [CCode (cname = "SANE_TITLE_BACKTRACK", cheader_filename = "sane/saneopts.h")] + public static string TITLE_BACKTRACK; + [CCode (cname = "SANE_TITLE_SCAN_TL_X", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_TL_X; + [CCode (cname = "SANE_TITLE_SCAN_TL_Y", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_TL_Y; + [CCode (cname = "SANE_TITLE_SCAN_BR_X", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_BR_X; + [CCode (cname = "SANE_TITLE_SCAN_BR_Y", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_BR_Y; + [CCode (cname = "SANE_TITLE_SCAN_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_RESOLUTION; + [CCode (cname = "SANE_TITLE_SCAN_X_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_X_RESOLUTION; + [CCode (cname = "SANE_TITLE_SCAN_Y_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_Y_RESOLUTION; + [CCode (cname = "SANE_TITLE_PAGE_WIDTH", cheader_filename = "sane/saneopts.h")] + public static string TITLE_PAGE_WIDTH; + [CCode (cname = "SANE_TITLE_PAGE_HEIGHT", cheader_filename = "sane/saneopts.h")] + public static string TITLE_PAGE_HEIGHT; + [CCode (cname = "SANE_TITLE_CUSTOM_GAMMA", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CUSTOM_GAMMA; + [CCode (cname = "SANE_TITLE_GAMMA_VECTOR", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GAMMA_VECTOR; + [CCode (cname = "SANE_TITLE_GAMMA_VECTOR_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GAMMA_VECTOR_R; + [CCode (cname = "SANE_TITLE_GAMMA_VECTOR_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GAMMA_VECTOR_G; + [CCode (cname = "SANE_TITLE_GAMMA_VECTOR_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GAMMA_VECTOR_B; + [CCode (cname = "SANE_TITLE_BRIGHTNESS", cheader_filename = "sane/saneopts.h")] + public static string TITLE_BRIGHTNESS; + [CCode (cname = "SANE_TITLE_CONTRAST", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CONTRAST; + [CCode (cname = "SANE_TITLE_GRAIN_SIZE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_GRAIN_SIZE; + [CCode (cname = "SANE_TITLE_HALFTONE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HALFTONE; + [CCode (cname = "SANE_TITLE_BLACK_LEVEL", cheader_filename = "sane/saneopts.h")] + public static string TITLE_BLACK_LEVEL; + [CCode (cname = "SANE_TITLE_WHITE_LEVEL", cheader_filename = "sane/saneopts.h")] + public static string TITLE_WHITE_LEVEL; + [CCode (cname = "SANE_TITLE_WHITE_LEVEL_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_WHITE_LEVEL_R; + [CCode (cname = "SANE_TITLE_WHITE_LEVEL_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_WHITE_LEVEL_G; + [CCode (cname = "SANE_TITLE_WHITE_LEVEL_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_WHITE_LEVEL_B; + [CCode (cname = "SANE_TITLE_SHADOW", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SHADOW; + [CCode (cname = "SANE_TITLE_SHADOW_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SHADOW_R; + [CCode (cname = "SANE_TITLE_SHADOW_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SHADOW_G; + [CCode (cname = "SANE_TITLE_SHADOW_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SHADOW_B; + [CCode (cname = "SANE_TITLE_HIGHLIGHT", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HIGHLIGHT; + [CCode (cname = "SANE_TITLE_HIGHLIGHT_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HIGHLIGHT_R; + [CCode (cname = "SANE_TITLE_HIGHLIGHT_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HIGHLIGHT_G; + [CCode (cname = "SANE_TITLE_HIGHLIGHT_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HIGHLIGHT_B; + [CCode (cname = "SANE_TITLE_HUE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HUE; + [CCode (cname = "SANE_TITLE_SATURATION", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SATURATION; + [CCode (cname = "SANE_TITLE_FILE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_FILE; + [CCode (cname = "SANE_TITLE_HALFTONE_DIMENSION", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HALFTONE_DIMENSION; + [CCode (cname = "SANE_TITLE_HALFTONE_PATTERN", cheader_filename = "sane/saneopts.h")] + public static string TITLE_HALFTONE_PATTERN; + [CCode (cname = "SANE_TITLE_RESOLUTION_BIND", cheader_filename = "sane/saneopts.h")] + public static string TITLE_RESOLUTION_BIND; + [CCode (cname = "SANE_TITLE_NEGATIVE", cheader_filename = "sane/saneopts.h")] + public static string TITLE_NEGATIVE; + [CCode (cname = "SANE_TITLE_QUALITY_CAL", cheader_filename = "sane/saneopts.h")] + public static string TITLE_QUALITY_CAL; + [CCode (cname = "SANE_TITLE_DOR", cheader_filename = "sane/saneopts.h")] + public static string TITLE_DOR; + [CCode (cname = "SANE_TITLE_RGB_BIND", cheader_filename = "sane/saneopts.h")] + public static string TITLE_RGB_BIND; + [CCode (cname = "SANE_TITLE_THRESHOLD", cheader_filename = "sane/saneopts.h")] + public static string TITLE_THRESHOLD; + [CCode (cname = "SANE_TITLE_ANALOG_GAMMA", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ANALOG_GAMMA; + [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ANALOG_GAMMA_R; + [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ANALOG_GAMMA_G; + [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ANALOG_GAMMA_B; + [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_BIND", cheader_filename = "sane/saneopts.h")] + public static string TITLE_ANALOG_GAMMA_BIND; + [CCode (cname = "SANE_TITLE_WARMUP", cheader_filename = "sane/saneopts.h")] + public static string TITLE_WARMUP; + [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CAL_EXPOS_TIME; + [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CAL_EXPOS_TIME_R; + [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CAL_EXPOS_TIME_G; + [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CAL_EXPOS_TIME_B; + [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_EXPOS_TIME; + [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_EXPOS_TIME_R; + [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_EXPOS_TIME_G; + [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_EXPOS_TIME_B; + [CCode (cname = "SANE_TITLE_SELECT_EXPOSURE_TIME", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SELECT_EXPOSURE_TIME; + [CCode (cname = "SANE_TITLE_CAL_LAMP_DEN", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CAL_LAMP_DEN; + [CCode (cname = "SANE_TITLE_SCAN_LAMP_DEN", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN_LAMP_DEN; + [CCode (cname = "SANE_TITLE_SELECT_LAMP_DENSITY", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SELECT_LAMP_DENSITY; + [CCode (cname = "SANE_TITLE_LAMP_OFF_AT_EXIT", cheader_filename = "sane/saneopts.h")] + public static string TITLE_LAMP_OFF_AT_EXIT; + [CCode (cname = "SANE_TITLE_SCAN", cheader_filename = "sane/saneopts.h")] + public static string TITLE_SCAN; + [CCode (cname = "SANE_TITLE_EMAIL", cheader_filename = "sane/saneopts.h")] + public static string TITLE_EMAIL; + [CCode (cname = "SANE_TITLE_FAX", cheader_filename = "sane/saneopts.h")] + public static string TITLE_FAX; + [CCode (cname = "SANE_TITLE_COPY", cheader_filename = "sane/saneopts.h")] + public static string TITLE_COPY; + [CCode (cname = "SANE_TITLE_PDF", cheader_filename = "sane/saneopts.h")] + public static string TITLE_PDF; + [CCode (cname = "SANE_TITLE_CANCEL", cheader_filename = "sane/saneopts.h")] + public static string TITLE_CANCEL; + [CCode (cname = "SANE_TITLE_PAGE_LOADED", cheader_filename = "sane/saneopts.h")] + public static string TITLE_PAGE_LOADED; + [CCode (cname = "SANE_TITLE_COVER_OPEN", cheader_filename = "sane/saneopts.h")] + public static string TITLE_COVER_OPEN; + [CCode (cname = "SANE_DESC_NUM_OPTIONS", cheader_filename = "sane/saneopts.h")] + public static string DESC_NUM_OPTIONS; + [CCode (cname = "SANE_DESC_STANDARD", cheader_filename = "sane/saneopts.h")] + public static string DESC_STANDARD; + [CCode (cname = "SANE_DESC_GEOMETRY", cheader_filename = "sane/saneopts.h")] + public static string DESC_GEOMETRY; + [CCode (cname = "SANE_DESC_ENHANCEMENT", cheader_filename = "sane/saneopts.h")] + public static string DESC_ENHANCEMENT; + [CCode (cname = "SANE_DESC_ADVANCED", cheader_filename = "sane/saneopts.h")] + public static string DESC_ADVANCED; + [CCode (cname = "SANE_DESC_SENSORS", cheader_filename = "sane/saneopts.h")] + public static string DESC_SENSORS; + [CCode (cname = "SANE_DESC_PREVIEW", cheader_filename = "sane/saneopts.h")] + public static string DESC_PREVIEW; + [CCode (cname = "SANE_DESC_GRAY_PREVIEW", cheader_filename = "sane/saneopts.h")] + public static string DESC_GRAY_PREVIEW; + [CCode (cname = "SANE_DESC_BIT_DEPTH", cheader_filename = "sane/saneopts.h")] + public static string DESC_BIT_DEPTH; + [CCode (cname = "SANE_DESC_SCAN_MODE", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_MODE; + [CCode (cname = "SANE_DESC_SCAN_SPEED", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_SPEED; + [CCode (cname = "SANE_DESC_SCAN_SOURCE", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_SOURCE; + [CCode (cname = "SANE_DESC_BACKTRACK", cheader_filename = "sane/saneopts.h")] + public static string DESC_BACKTRACK; + [CCode (cname = "SANE_DESC_SCAN_TL_X", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_TL_X; + [CCode (cname = "SANE_DESC_SCAN_TL_Y", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_TL_Y; + [CCode (cname = "SANE_DESC_SCAN_BR_X", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_BR_X; + [CCode (cname = "SANE_DESC_SCAN_BR_Y", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_BR_Y; + [CCode (cname = "SANE_DESC_SCAN_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_RESOLUTION; + [CCode (cname = "SANE_DESC_SCAN_X_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_X_RESOLUTION; + [CCode (cname = "SANE_DESC_SCAN_Y_RESOLUTION", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_Y_RESOLUTION; + [CCode (cname = "SANE_DESC_PAGE_WIDTH", cheader_filename = "sane/saneopts.h")] + public static string DESC_PAGE_WIDTH; + [CCode (cname = "SANE_DESC_PAGE_HEIGHT", cheader_filename = "sane/saneopts.h")] + public static string DESC_PAGE_HEIGHT; + [CCode (cname = "SANE_DESC_CUSTOM_GAMMA", cheader_filename = "sane/saneopts.h")] + public static string DESC_CUSTOM_GAMMA; + [CCode (cname = "SANE_DESC_GAMMA_VECTOR", cheader_filename = "sane/saneopts.h")] + public static string DESC_GAMMA_VECTOR; + [CCode (cname = "SANE_DESC_GAMMA_VECTOR_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_GAMMA_VECTOR_R; + [CCode (cname = "SANE_DESC_GAMMA_VECTOR_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_GAMMA_VECTOR_G; + [CCode (cname = "SANE_DESC_GAMMA_VECTOR_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_GAMMA_VECTOR_B; + [CCode (cname = "SANE_DESC_BRIGHTNESS", cheader_filename = "sane/saneopts.h")] + public static string DESC_BRIGHTNESS; + [CCode (cname = "SANE_DESC_CONTRAST", cheader_filename = "sane/saneopts.h")] + public static string DESC_CONTRAST; + [CCode (cname = "SANE_DESC_GRAIN_SIZE", cheader_filename = "sane/saneopts.h")] + public static string DESC_GRAIN_SIZE; + [CCode (cname = "SANE_DESC_HALFTONE", cheader_filename = "sane/saneopts.h")] + public static string DESC_HALFTONE; + [CCode (cname = "SANE_DESC_BLACK_LEVEL", cheader_filename = "sane/saneopts.h")] + public static string DESC_BLACK_LEVEL; + [CCode (cname = "SANE_DESC_WHITE_LEVEL", cheader_filename = "sane/saneopts.h")] + public static string DESC_WHITE_LEVEL; + [CCode (cname = "SANE_DESC_WHITE_LEVEL_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_WHITE_LEVEL_R; + [CCode (cname = "SANE_DESC_WHITE_LEVEL_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_WHITE_LEVEL_G; + [CCode (cname = "SANE_DESC_WHITE_LEVEL_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_WHITE_LEVEL_B; + [CCode (cname = "SANE_DESC_SHADOW", cheader_filename = "sane/saneopts.h")] + public static string DESC_SHADOW; + [CCode (cname = "SANE_DESC_SHADOW_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_SHADOW_R; + [CCode (cname = "SANE_DESC_SHADOW_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_SHADOW_G; + [CCode (cname = "SANE_DESC_SHADOW_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_SHADOW_B; + [CCode (cname = "SANE_DESC_HIGHLIGHT", cheader_filename = "sane/saneopts.h")] + public static string DESC_HIGHLIGHT; + [CCode (cname = "SANE_DESC_HIGHLIGHT_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_HIGHLIGHT_R; + [CCode (cname = "SANE_DESC_HIGHLIGHT_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_HIGHLIGHT_G; + [CCode (cname = "SANE_DESC_HIGHLIGHT_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_HIGHLIGHT_B; + [CCode (cname = "SANE_DESC_HUE", cheader_filename = "sane/saneopts.h")] + public static string DESC_HUE; + [CCode (cname = "SANE_DESC_SATURATION", cheader_filename = "sane/saneopts.h")] + public static string DESC_SATURATION; + [CCode (cname = "SANE_DESC_FILE", cheader_filename = "sane/saneopts.h")] + public static string DESC_FILE; + [CCode (cname = "SANE_DESC_HALFTONE_DIMENSION", cheader_filename = "sane/saneopts.h")] + public static string DESC_HALFTONE_DIMENSION; + [CCode (cname = "SANE_DESC_HALFTONE_PATTERN", cheader_filename = "sane/saneopts.h")] + public static string DESC_HALFTONE_PATTERN; + [CCode (cname = "SANE_DESC_RESOLUTION_BIND", cheader_filename = "sane/saneopts.h")] + public static string DESC_RESOLUTION_BIND; + [CCode (cname = "SANE_DESC_NEGATIVE", cheader_filename = "sane/saneopts.h")] + public static string DESC_NEGATIVE; + [CCode (cname = "SANE_DESC_QUALITY_CAL", cheader_filename = "sane/saneopts.h")] + public static string DESC_QUALITY_CAL; + [CCode (cname = "SANE_DESC_DOR", cheader_filename = "sane/saneopts.h")] + public static string DESC_DOR; + [CCode (cname = "SANE_DESC_RGB_BIND", cheader_filename = "sane/saneopts.h")] + public static string DESC_RGB_BIND; + [CCode (cname = "SANE_DESC_THRESHOLD", cheader_filename = "sane/saneopts.h")] + public static string DESC_THRESHOLD; + [CCode (cname = "SANE_DESC_ANALOG_GAMMA", cheader_filename = "sane/saneopts.h")] + public static string DESC_ANALOG_GAMMA; + [CCode (cname = "SANE_DESC_ANALOG_GAMMA_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_ANALOG_GAMMA_R; + [CCode (cname = "SANE_DESC_ANALOG_GAMMA_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_ANALOG_GAMMA_G; + [CCode (cname = "SANE_DESC_ANALOG_GAMMA_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_ANALOG_GAMMA_B; + [CCode (cname = "SANE_DESC_ANALOG_GAMMA_BIND", cheader_filename = "sane/saneopts.h")] + public static string DESC_ANALOG_GAMMA_BIND; + [CCode (cname = "SANE_DESC_WARMUP", cheader_filename = "sane/saneopts.h")] + public static string DESC_WARMUP; + [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME", cheader_filename = "sane/saneopts.h")] + public static string DESC_CAL_EXPOS_TIME; + [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_CAL_EXPOS_TIME_R; + [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_CAL_EXPOS_TIME_G; + [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_CAL_EXPOS_TIME_B; + [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_EXPOS_TIME; + [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_EXPOS_TIME_R; + [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_EXPOS_TIME_G; + [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_EXPOS_TIME_B; + [CCode (cname = "SANE_DESC_SELECT_EXPOSURE_TIME", cheader_filename = "sane/saneopts.h")] + public static string DESC_SELECT_EXPOSURE_TIME; + [CCode (cname = "SANE_DESC_CAL_LAMP_DEN", cheader_filename = "sane/saneopts.h")] + public static string DESC_CAL_LAMP_DEN; + [CCode (cname = "SANE_DESC_SCAN_LAMP_DEN", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN_LAMP_DEN; + [CCode (cname = "SANE_DESC_SELECT_LAMP_DENSITY", cheader_filename = "sane/saneopts.h")] + public static string DESC_SELECT_LAMP_DENSITY; + [CCode (cname = "SANE_DESC_LAMP_OFF_AT_EXIT", cheader_filename = "sane/saneopts.h")] + public static string DESC_LAMP_OFF_AT_EXIT; + [CCode (cname = "SANE_DESC_SCAN", cheader_filename = "sane/saneopts.h")] + public static string DESC_SCAN; + [CCode (cname = "SANE_DESC_EMAIL", cheader_filename = "sane/saneopts.h")] + public static string DESC_EMAIL; + [CCode (cname = "SANE_DESC_FAX", cheader_filename = "sane/saneopts.h")] + public static string DESC_FAX; + [CCode (cname = "SANE_DESC_COPY", cheader_filename = "sane/saneopts.h")] + public static string DESC_COPY; + [CCode (cname = "SANE_DESC_PDF", cheader_filename = "sane/saneopts.h")] + public static string DESC_PDF; + [CCode (cname = "SANE_DESC_CANCEL", cheader_filename = "sane/saneopts.h")] + public static string DESC_CANCEL; + [CCode (cname = "SANE_DESC_PAGE_LOADED", cheader_filename = "sane/saneopts.h")] + public static string DESC_PAGE_LOADED; + [CCode (cname = "SANE_DESC_COVER_OPEN", cheader_filename = "sane/saneopts.h")] + public static string DESC_COVER_OPEN; + [CCode (cname = "SANE_VALUE_SCAN_MODE_COLOR", cheader_filename = "sane/saneopts.h")] + public static string VALUE_SCAN_MODE_COLOR; + [CCode (cname = "SANE_VALUE_SCAN_MODE_COLOR_LINEART", cheader_filename = "sane/saneopts.h")] + public static string VALUE_SCAN_MODE_COLOR_LINEART; + [CCode (cname = "SANE_VALUE_SCAN_MODE_COLOR_HALFTONE", cheader_filename = "sane/saneopts.h")] + public static string VALUE_SCAN_MODE_COLOR_HALFTONE; + [CCode (cname = "SANE_VALUE_SCAN_MODE_GRAY", cheader_filename = "sane/saneopts.h")] + public static string VALUE_SCAN_MODE_GRAY; + [CCode (cname = "SANE_VALUE_SCAN_MODE_HALFTONE", cheader_filename = "sane/saneopts.h")] + public static string VALUE_SCAN_MODE_HALFTONE; + [CCode (cname = "SANE_VALUE_SCAN_MODE_LINEART", cheader_filename = "sane/saneopts.h")] + public static string VALUE_SCAN_MODE_LINEART; +} + diff --git a/src/scanner.c b/src/scanner.c index ff8a994..e7e83cc 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -1,1714 +1,6089 @@ +/* scanner.c generated by valac 0.13.1, the Vala compiler + * generated from scanner.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. See http://www.gnu.org/copyleft/gpl.html the full text of the * license. */ +/* TODO: Could indicate the start of the next page immediately after the last page is received (i.e. before the sane_cancel()) */ +#include <glib.h> +#include <glib-object.h> #include <stdlib.h> #include <string.h> +#include <float.h> #include <math.h> #include <sane/sane.h> +#include <glib/gi18n-lib.h> #include <sane/saneopts.h> -#include <glib/gi18n.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_SCAN_DEVICE (scan_device_get_type ()) +#define SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_DEVICE, ScanDevice)) +#define SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_DEVICE, ScanDeviceClass)) +#define IS_SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_DEVICE)) +#define IS_SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_DEVICE)) +#define SCAN_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_DEVICE, ScanDeviceClass)) + +typedef struct _ScanDevice ScanDevice; +typedef struct _ScanDeviceClass ScanDeviceClass; +typedef struct _ScanDevicePrivate ScanDevicePrivate; +#define _g_free0(var) (var = (g_free (var), NULL)) +typedef struct _ParamSpecScanDevice ParamSpecScanDevice; + +#define TYPE_SCAN_PAGE_INFO (scan_page_info_get_type ()) +#define SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfo)) +#define SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) +#define IS_SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_PAGE_INFO)) +#define IS_SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_PAGE_INFO)) +#define SCAN_PAGE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) + +typedef struct _ScanPageInfo ScanPageInfo; +typedef struct _ScanPageInfoClass ScanPageInfoClass; +typedef struct _ScanPageInfoPrivate ScanPageInfoPrivate; +typedef struct _ParamSpecScanPageInfo ParamSpecScanPageInfo; + +#define TYPE_SCAN_LINE (scan_line_get_type ()) +#define SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_LINE, ScanLine)) +#define SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_LINE, ScanLineClass)) +#define IS_SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_LINE)) +#define IS_SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_LINE)) +#define SCAN_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_LINE, ScanLineClass)) + +typedef struct _ScanLine ScanLine; +typedef struct _ScanLineClass ScanLineClass; +typedef struct _ScanLinePrivate ScanLinePrivate; +typedef struct _ParamSpecScanLine ParamSpecScanLine; + +#define TYPE_SCAN_MODE (scan_mode_get_type ()) + +#define TYPE_SCAN_TYPE (scan_type_get_type ()) + +#define TYPE_SCAN_OPTIONS (scan_options_get_type ()) +#define SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_OPTIONS, ScanOptions)) +#define SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_OPTIONS, ScanOptionsClass)) +#define IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_OPTIONS)) +#define IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_OPTIONS)) +#define SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_OPTIONS, ScanOptionsClass)) + +typedef struct _ScanOptions ScanOptions; +typedef struct _ScanOptionsClass ScanOptionsClass; +typedef struct _ScanOptionsPrivate ScanOptionsPrivate; +typedef struct _ParamSpecScanOptions ParamSpecScanOptions; + +#define TYPE_SCAN_JOB (scan_job_get_type ()) +#define SCAN_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_JOB, ScanJob)) +#define SCAN_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_JOB, ScanJobClass)) +#define IS_SCAN_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_JOB)) +#define IS_SCAN_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_JOB)) +#define SCAN_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_JOB, ScanJobClass)) + +typedef struct _ScanJob ScanJob; +typedef struct _ScanJobClass ScanJobClass; +typedef struct _ScanJobPrivate ScanJobPrivate; +typedef struct _ParamSpecScanJob ParamSpecScanJob; + +#define TYPE_REQUEST (request_get_type ()) +#define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST, Request)) +#define REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST, RequestClass)) +#define IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST)) +#define IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST)) +#define REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST, RequestClass)) + +typedef struct _Request Request; +typedef struct _RequestClass RequestClass; +typedef struct _RequestPrivate RequestPrivate; +typedef struct _ParamSpecRequest ParamSpecRequest; + +#define TYPE_REQUEST_REDETECT (request_redetect_get_type ()) +#define REQUEST_REDETECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_REDETECT, RequestRedetect)) +#define REQUEST_REDETECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_REDETECT, RequestRedetectClass)) +#define IS_REQUEST_REDETECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_REDETECT)) +#define IS_REQUEST_REDETECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_REDETECT)) +#define REQUEST_REDETECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_REDETECT, RequestRedetectClass)) + +typedef struct _RequestRedetect RequestRedetect; +typedef struct _RequestRedetectClass RequestRedetectClass; +typedef struct _RequestRedetectPrivate RequestRedetectPrivate; + +#define TYPE_REQUEST_CANCEL (request_cancel_get_type ()) +#define REQUEST_CANCEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_CANCEL, RequestCancel)) +#define REQUEST_CANCEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_CANCEL, RequestCancelClass)) +#define IS_REQUEST_CANCEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_CANCEL)) +#define IS_REQUEST_CANCEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_CANCEL)) +#define REQUEST_CANCEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_CANCEL, RequestCancelClass)) + +typedef struct _RequestCancel RequestCancel; +typedef struct _RequestCancelClass RequestCancelClass; +typedef struct _RequestCancelPrivate RequestCancelPrivate; + +#define TYPE_REQUEST_START_SCAN (request_start_scan_get_type ()) +#define REQUEST_START_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_START_SCAN, RequestStartScan)) +#define REQUEST_START_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_START_SCAN, RequestStartScanClass)) +#define IS_REQUEST_START_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_START_SCAN)) +#define IS_REQUEST_START_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_START_SCAN)) +#define REQUEST_START_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_START_SCAN, RequestStartScanClass)) + +typedef struct _RequestStartScan RequestStartScan; +typedef struct _RequestStartScanClass RequestStartScanClass; +typedef struct _RequestStartScanPrivate RequestStartScanPrivate; +#define _scan_job_unref0(var) ((var == NULL) ? NULL : (var = (scan_job_unref (var), NULL))) + +#define TYPE_REQUEST_QUIT (request_quit_get_type ()) +#define REQUEST_QUIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_QUIT, RequestQuit)) +#define REQUEST_QUIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_QUIT, RequestQuitClass)) +#define IS_REQUEST_QUIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_QUIT)) +#define IS_REQUEST_QUIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_QUIT)) +#define REQUEST_QUIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_QUIT, RequestQuitClass)) + +typedef struct _RequestQuit RequestQuit; +typedef struct _RequestQuitClass RequestQuitClass; +typedef struct _RequestQuitPrivate RequestQuitPrivate; + +#define TYPE_CREDENTIALS (credentials_get_type ()) +#define CREDENTIALS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CREDENTIALS, Credentials)) +#define CREDENTIALS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CREDENTIALS, CredentialsClass)) +#define IS_CREDENTIALS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CREDENTIALS)) +#define IS_CREDENTIALS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CREDENTIALS)) +#define CREDENTIALS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CREDENTIALS, CredentialsClass)) + +typedef struct _Credentials Credentials; +typedef struct _CredentialsClass CredentialsClass; +typedef struct _CredentialsPrivate CredentialsPrivate; +typedef struct _ParamSpecCredentials ParamSpecCredentials; + +#define TYPE_SCAN_STATE (scan_state_get_type ()) + +#define TYPE_NOTIFY (notify_get_type ()) +#define NOTIFY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY, Notify)) +#define NOTIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY, NotifyClass)) +#define IS_NOTIFY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY)) +#define IS_NOTIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY)) +#define NOTIFY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY, NotifyClass)) + +typedef struct _Notify Notify; +typedef struct _NotifyClass NotifyClass; +typedef struct _NotifyPrivate NotifyPrivate; + +#define TYPE_SCANNER (scanner_get_type ()) +#define SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCANNER, Scanner)) +#define SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCANNER, ScannerClass)) +#define IS_SCANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCANNER)) +#define IS_SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCANNER)) +#define SCANNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCANNER, ScannerClass)) + +typedef struct _Scanner Scanner; +typedef struct _ScannerClass ScannerClass; +typedef struct _ParamSpecNotify ParamSpecNotify; + +#define TYPE_NOTIFY_SCANNING_CHANGED (notify_scanning_changed_get_type ()) +#define NOTIFY_SCANNING_CHANGED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_SCANNING_CHANGED, NotifyScanningChanged)) +#define NOTIFY_SCANNING_CHANGED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_SCANNING_CHANGED, NotifyScanningChangedClass)) +#define IS_NOTIFY_SCANNING_CHANGED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_SCANNING_CHANGED)) +#define IS_NOTIFY_SCANNING_CHANGED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_SCANNING_CHANGED)) +#define NOTIFY_SCANNING_CHANGED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_SCANNING_CHANGED, NotifyScanningChangedClass)) + +typedef struct _NotifyScanningChanged NotifyScanningChanged; +typedef struct _NotifyScanningChangedClass NotifyScanningChangedClass; +typedef struct _NotifyScanningChangedPrivate NotifyScanningChangedPrivate; + +#define TYPE_NOTIFY_UPDATE_DEVICES (notify_update_devices_get_type ()) +#define NOTIFY_UPDATE_DEVICES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevices)) +#define NOTIFY_UPDATE_DEVICES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevicesClass)) +#define IS_NOTIFY_UPDATE_DEVICES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_UPDATE_DEVICES)) +#define IS_NOTIFY_UPDATE_DEVICES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_UPDATE_DEVICES)) +#define NOTIFY_UPDATE_DEVICES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevicesClass)) + +typedef struct _NotifyUpdateDevices NotifyUpdateDevices; +typedef struct _NotifyUpdateDevicesClass NotifyUpdateDevicesClass; +typedef struct _NotifyUpdateDevicesPrivate NotifyUpdateDevicesPrivate; +#define __g_list_free__scan_device_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__scan_device_unref0_ (var), NULL))) + +#define TYPE_NOTIFY_REQUEST_AUTHORIZATION (notify_request_authorization_get_type ()) +#define NOTIFY_REQUEST_AUTHORIZATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorization)) +#define NOTIFY_REQUEST_AUTHORIZATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorizationClass)) +#define IS_NOTIFY_REQUEST_AUTHORIZATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_REQUEST_AUTHORIZATION)) +#define IS_NOTIFY_REQUEST_AUTHORIZATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_REQUEST_AUTHORIZATION)) +#define NOTIFY_REQUEST_AUTHORIZATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorizationClass)) + +typedef struct _NotifyRequestAuthorization NotifyRequestAuthorization; +typedef struct _NotifyRequestAuthorizationClass NotifyRequestAuthorizationClass; +typedef struct _NotifyRequestAuthorizationPrivate NotifyRequestAuthorizationPrivate; + +#define TYPE_NOTIFY_SCAN_FAILED (notify_scan_failed_get_type ()) +#define NOTIFY_SCAN_FAILED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailed)) +#define NOTIFY_SCAN_FAILED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailedClass)) +#define IS_NOTIFY_SCAN_FAILED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_SCAN_FAILED)) +#define IS_NOTIFY_SCAN_FAILED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_SCAN_FAILED)) +#define NOTIFY_SCAN_FAILED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailedClass)) + +typedef struct _NotifyScanFailed NotifyScanFailed; +typedef struct _NotifyScanFailedClass NotifyScanFailedClass; +typedef struct _NotifyScanFailedPrivate NotifyScanFailedPrivate; + +#define TYPE_NOTIFY_DOCUMENT_DONE (notify_document_done_get_type ()) +#define NOTIFY_DOCUMENT_DONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_DOCUMENT_DONE, NotifyDocumentDone)) +#define NOTIFY_DOCUMENT_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_DOCUMENT_DONE, NotifyDocumentDoneClass)) +#define IS_NOTIFY_DOCUMENT_DONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_DOCUMENT_DONE)) +#define IS_NOTIFY_DOCUMENT_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_DOCUMENT_DONE)) +#define NOTIFY_DOCUMENT_DONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_DOCUMENT_DONE, NotifyDocumentDoneClass)) + +typedef struct _NotifyDocumentDone NotifyDocumentDone; +typedef struct _NotifyDocumentDoneClass NotifyDocumentDoneClass; +typedef struct _NotifyDocumentDonePrivate NotifyDocumentDonePrivate; + +#define TYPE_NOTIFY_EXPECT_PAGE (notify_expect_page_get_type ()) +#define NOTIFY_EXPECT_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_EXPECT_PAGE, NotifyExpectPage)) +#define NOTIFY_EXPECT_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_EXPECT_PAGE, NotifyExpectPageClass)) +#define IS_NOTIFY_EXPECT_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_EXPECT_PAGE)) +#define IS_NOTIFY_EXPECT_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_EXPECT_PAGE)) +#define NOTIFY_EXPECT_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_EXPECT_PAGE, NotifyExpectPageClass)) + +typedef struct _NotifyExpectPage NotifyExpectPage; +typedef struct _NotifyExpectPageClass NotifyExpectPageClass; +typedef struct _NotifyExpectPagePrivate NotifyExpectPagePrivate; + +#define TYPE_NOTIFY_GOT_PAGE_INFO (notify_got_page_info_get_type ()) +#define NOTIFY_GOT_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfo)) +#define NOTIFY_GOT_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfoClass)) +#define IS_NOTIFY_GOT_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_GOT_PAGE_INFO)) +#define IS_NOTIFY_GOT_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_GOT_PAGE_INFO)) +#define NOTIFY_GOT_PAGE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfoClass)) + +typedef struct _NotifyGotPageInfo NotifyGotPageInfo; +typedef struct _NotifyGotPageInfoClass NotifyGotPageInfoClass; +typedef struct _NotifyGotPageInfoPrivate NotifyGotPageInfoPrivate; +#define _scan_page_info_unref0(var) ((var == NULL) ? NULL : (var = (scan_page_info_unref (var), NULL))) + +#define TYPE_NOTIFY_PAGE_DONE (notify_page_done_get_type ()) +#define NOTIFY_PAGE_DONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_PAGE_DONE, NotifyPageDone)) +#define NOTIFY_PAGE_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_PAGE_DONE, NotifyPageDoneClass)) +#define IS_NOTIFY_PAGE_DONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_PAGE_DONE)) +#define IS_NOTIFY_PAGE_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_PAGE_DONE)) +#define NOTIFY_PAGE_DONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_PAGE_DONE, NotifyPageDoneClass)) + +typedef struct _NotifyPageDone NotifyPageDone; +typedef struct _NotifyPageDoneClass NotifyPageDoneClass; +typedef struct _NotifyPageDonePrivate NotifyPageDonePrivate; + +#define TYPE_NOTIFY_GOT_LINE (notify_got_line_get_type ()) +#define NOTIFY_GOT_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_GOT_LINE, NotifyGotLine)) +#define NOTIFY_GOT_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_GOT_LINE, NotifyGotLineClass)) +#define IS_NOTIFY_GOT_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_GOT_LINE)) +#define IS_NOTIFY_GOT_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_GOT_LINE)) +#define NOTIFY_GOT_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_GOT_LINE, NotifyGotLineClass)) + +typedef struct _NotifyGotLine NotifyGotLine; +typedef struct _NotifyGotLineClass NotifyGotLineClass; +typedef struct _NotifyGotLinePrivate NotifyGotLinePrivate; +#define _scan_line_unref0(var) ((var == NULL) ? NULL : (var = (scan_line_unref (var), NULL))) +typedef struct _ScannerPrivate ScannerPrivate; +#define _g_async_queue_unref0(var) ((var == NULL) ? NULL : (var = (g_async_queue_unref (var), NULL))) +#define __g_list_free__scan_job_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__scan_job_unref0_ (var), NULL))) +#define _scanner_unref0(var) ((var == NULL) ? NULL : (var = (scanner_unref (var), NULL))) +#define _notify_unref0(var) ((var == NULL) ? NULL : (var = (notify_unref (var), NULL))) +#define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +#define _scan_device_unref0(var) ((var == NULL) ? NULL : (var = (scan_device_unref (var), NULL))) +#define _credentials_unref0(var) ((var == NULL) ? NULL : (var = (credentials_unref (var), NULL))) +#define _request_unref0(var) ((var == NULL) ? NULL : (var = (request_unref (var), NULL))) +typedef struct _ParamSpecScanner ParamSpecScanner; + +struct _ScanDevice { + GTypeInstance parent_instance; + volatile int ref_count; + ScanDevicePrivate * priv; + gchar* name; + gchar* label; +}; -#include "scanner.h" +struct _ScanDeviceClass { + GTypeClass parent_class; + void (*finalize) (ScanDevice *self); +}; -/* TODO: Could indicate the start of the next page immediately after the last page is received (i.e. before the sane_cancel()) */ +struct _ParamSpecScanDevice { + GParamSpec parent_instance; +}; + +struct _ScanPageInfo { + GTypeInstance parent_instance; + volatile int ref_count; + ScanPageInfoPrivate * priv; + gint width; + gint height; + gint depth; + gint n_channels; + gdouble dpi; + gchar* device; +}; + +struct _ScanPageInfoClass { + GTypeClass parent_class; + void (*finalize) (ScanPageInfo *self); +}; + +struct _ParamSpecScanPageInfo { + GParamSpec parent_instance; +}; + +struct _ScanLine { + GTypeInstance parent_instance; + volatile int ref_count; + ScanLinePrivate * priv; + gint number; + gint n_lines; + gint width; + gint depth; + gint channel; + guchar* data; + gint data_length1; + gint data_length; +}; + +struct _ScanLineClass { + GTypeClass parent_class; + void (*finalize) (ScanLine *self); +}; + +struct _ParamSpecScanLine { + GParamSpec parent_instance; +}; + +typedef enum { + SCAN_MODE_DEFAULT, + SCAN_MODE_COLOR, + SCAN_MODE_GRAY, + SCAN_MODE_LINEART +} ScanMode; + +typedef enum { + SCAN_TYPE_SINGLE, + SCAN_TYPE_ADF_FRONT, + SCAN_TYPE_ADF_BACK, + SCAN_TYPE_ADF_BOTH +} ScanType; + +struct _ScanOptions { + GTypeInstance parent_instance; + volatile int ref_count; + ScanOptionsPrivate * priv; + gint dpi; + ScanMode scan_mode; + gint depth; + ScanType type; + gint paper_width; + gint paper_height; +}; + +struct _ScanOptionsClass { + GTypeClass parent_class; + void (*finalize) (ScanOptions *self); +}; + +struct _ParamSpecScanOptions { + GParamSpec parent_instance; +}; + +struct _ScanJob { + GTypeInstance parent_instance; + volatile int ref_count; + ScanJobPrivate * priv; + gchar* device; + gdouble dpi; + ScanMode scan_mode; + gint depth; + ScanType type; + gint page_width; + gint page_height; +}; + +struct _ScanJobClass { + GTypeClass parent_class; + void (*finalize) (ScanJob *self); +}; + +struct _ParamSpecScanJob { + GParamSpec parent_instance; +}; + +struct _Request { + GTypeInstance parent_instance; + volatile int ref_count; + RequestPrivate * priv; +}; + +struct _RequestClass { + GTypeClass parent_class; + void (*finalize) (Request *self); +}; -enum { - UPDATE_DEVICES, - AUTHORIZE, - EXPECT_PAGE, - GOT_PAGE_INFO, - GOT_LINE, - SCAN_FAILED, - PAGE_DONE, - DOCUMENT_DONE, - SCANNING_CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0, }; - -typedef struct -{ - Scanner *instance; - guint sig; - gpointer data; -} SignalInfo; - -typedef struct -{ - gchar *device; - gdouble dpi; - ScanMode scan_mode; - gint depth; - gboolean type; - gint page_width, page_height; -} ScanJob; - -typedef struct -{ - enum - { - REQUEST_CANCEL, - REQUEST_REDETECT, - REQUEST_START_SCAN, - REQUEST_QUIT - } type; - ScanJob *job; -} ScanRequest; - -typedef struct -{ - gchar *username, *password; -} Credentials; - -typedef enum -{ - STATE_IDLE = 0, - STATE_REDETECT, - STATE_OPEN, - STATE_GET_OPTION, - STATE_START, - STATE_GET_PARAMETERS, - STATE_READ +struct _ParamSpecRequest { + GParamSpec parent_instance; +}; + +struct _RequestRedetect { + Request parent_instance; + RequestRedetectPrivate * priv; +}; + +struct _RequestRedetectClass { + RequestClass parent_class; +}; + +struct _RequestCancel { + Request parent_instance; + RequestCancelPrivate * priv; +}; + +struct _RequestCancelClass { + RequestClass parent_class; +}; + +struct _RequestStartScan { + Request parent_instance; + RequestStartScanPrivate * priv; + ScanJob* job; +}; + +struct _RequestStartScanClass { + RequestClass parent_class; +}; + +struct _RequestQuit { + Request parent_instance; + RequestQuitPrivate * priv; +}; + +struct _RequestQuitClass { + RequestClass parent_class; +}; + +struct _Credentials { + GTypeInstance parent_instance; + volatile int ref_count; + CredentialsPrivate * priv; + gchar* username; + gchar* password; +}; + +struct _CredentialsClass { + GTypeClass parent_class; + void (*finalize) (Credentials *self); +}; + +struct _ParamSpecCredentials { + GParamSpec parent_instance; +}; + +typedef enum { + SCAN_STATE_IDLE = 0, + SCAN_STATE_REDETECT, + SCAN_STATE_OPEN, + SCAN_STATE_GET_OPTION, + SCAN_STATE_START, + SCAN_STATE_GET_PARAMETERS, + SCAN_STATE_READ } ScanState; -struct ScannerPrivate -{ - GAsyncQueue *scan_queue, *authorize_queue; - GThread *thread; - - gchar *default_device; - - ScanState state; - gboolean redetect; - - GList *job_queue; - - /* Handle to SANE device */ - SANE_Handle handle; - gchar *current_device; - - SANE_Parameters parameters; - - /* Last option read */ - SANE_Int option_index; - - /* Option index for scan area */ - SANE_Int br_x_option_index, br_y_option_index; - - /* Buffer for received line */ - SANE_Byte *buffer; - SANE_Int buffer_size, n_used; - - SANE_Int bytes_remaining, line_count, pass_number, page_number, notified_page; - - gboolean scanning; -}; - -G_DEFINE_TYPE (Scanner, scanner, G_TYPE_OBJECT); - - -/* Table of scanner objects for each thread (required for authorization callback) */ -static GHashTable *scanners; - - -static gboolean -send_signal (SignalInfo *info) -{ - g_signal_emit (info->instance, signals[info->sig], 0, info->data); - - switch (info->sig) { - case UPDATE_DEVICES: - { - GList *iter, *devices = info->data; - for (iter = devices; iter; iter = iter->next) { - ScanDevice *device = iter->data; - g_free (device->name); - g_free (device->label); - g_free (device); - } - g_list_free (devices); - } - break; - case AUTHORIZE: - { - gchar *resource = info->data; - g_free (resource); - } - break; - case GOT_PAGE_INFO: - { - ScanPageInfo *page_info = info->data; - g_free (page_info); - } - break; - case GOT_LINE: - { - ScanLine *line = info->data; - g_free(line->data); - g_free(line); - } - break; - case SCAN_FAILED: - { - GError *error = info->data; - g_error_free (error); - } - break; - default: - case EXPECT_PAGE: - case PAGE_DONE: - case DOCUMENT_DONE: - case LAST_SIGNAL: - g_assert (info->data == NULL); - break; - } - g_free (info); - - return FALSE; -} - - -/* Emit signals in main loop */ -static void -emit_signal (Scanner *scanner, guint sig, gpointer data) -{ - SignalInfo *info; - - info = g_malloc(sizeof(SignalInfo)); - info->instance = scanner; - info->sig = sig; - info->data = data; - g_idle_add ((GSourceFunc) send_signal, info); -} - - -static void -set_scanning (Scanner *scanner, gboolean is_scanning) -{ - if ((scanner->priv->scanning && !is_scanning) || (!scanner->priv->scanning && is_scanning)) { - scanner->priv->scanning = is_scanning; - emit_signal (scanner, SCANNING_CHANGED, NULL); - } -} - - -static gint -get_device_weight (const gchar *device) -{ - /* NOTE: This is using trends in the naming of SANE devices, SANE should be able to provide this information better */ - - /* Use webcams as a last resort */ - if (g_str_has_prefix (device, "vfl:")) - return 2; - - /* Use locally connected devices first */ - if (strstr (device, "usb")) - return 0; - - return 1; -} - - -static gint -compare_devices (ScanDevice *device1, ScanDevice *device2) -{ - gint weight1, weight2; - - /* TODO: Should do some fuzzy matching on the last selected device and set that to the default */ - - weight1 = get_device_weight (device1->name); - weight2 = get_device_weight (device2->name); - if (weight1 != weight2) - return weight1 - weight2; - - return strcmp (device1->label, device2->label); -} - - -static const char * -get_status_string (SANE_Status status) -{ - struct { - SANE_Status status; - const char *name; - } status_names[] = { - { SANE_STATUS_GOOD, "SANE_STATUS_GOOD"}, - { SANE_STATUS_UNSUPPORTED, "SANE_STATUS_UNSUPPORTED"}, - { SANE_STATUS_CANCELLED, "SANE_STATUS_CANCELLED"}, - { SANE_STATUS_DEVICE_BUSY, "SANE_STATUS_DEVICE_BUSY"}, - { SANE_STATUS_INVAL, "SANE_STATUS_INVAL"}, - { SANE_STATUS_EOF, "SANE_STATUS_EOF"}, - { SANE_STATUS_JAMMED, "SANE_STATUS_JAMMED"}, - { SANE_STATUS_NO_DOCS, "SANE_STATUS_NO_DOCS"}, - { SANE_STATUS_COVER_OPEN, "SANE_STATUS_COVER_OPEN"}, - { SANE_STATUS_IO_ERROR, "SANE_STATUS_IO_ERROR"}, - { SANE_STATUS_NO_MEM, "SANE_STATUS_NO_MEM"}, - { SANE_STATUS_ACCESS_DENIED, "SANE_STATUS_ACCESS_DENIED"}, - { -1, NULL} - }; - static char *unknown_string = NULL; - int i; - - for (i = 0; status_names[i].name != NULL && status_names[i].status != status; i++); - - if (status_names[i].name == NULL) { - g_free (unknown_string); - unknown_string = g_strdup_printf ("SANE_STATUS(%d)", status); - return unknown_string; /* Note result is undefined on second call to this function */ - } - - return status_names[i].name; -} - - -static const char * -get_action_string (SANE_Action action) -{ - struct { - SANE_Action action; - const char *name; - } action_names[] = { - { SANE_ACTION_GET_VALUE, "SANE_ACTION_GET_VALUE" }, - { SANE_ACTION_SET_VALUE, "SANE_ACTION_SET_VALUE" }, - { SANE_ACTION_SET_AUTO, "SANE_ACTION_SET_AUTO" }, - { -1, NULL} - }; - static char *unknown_string = NULL; - int i; - - for (i = 0; action_names[i].name != NULL && action_names[i].action != action; i++); - - if (action_names[i].name == NULL) { - g_free (unknown_string); - unknown_string = g_strdup_printf ("SANE_ACTION(%d)", action); - return unknown_string; /* Note result is undefined on second call to this function */ - } - - return action_names[i].name; -} - - -static const char * -get_frame_string (SANE_Frame frame) -{ - struct { - SANE_Frame frame; - const char *name; - } frame_names[] = { - { SANE_FRAME_GRAY, "SANE_FRAME_GRAY" }, - { SANE_FRAME_RGB, "SANE_FRAME_RGB" }, - { SANE_FRAME_RED, "SANE_FRAME_RED" }, - { SANE_FRAME_GREEN, "SANE_FRAME_GREEN" }, - { SANE_FRAME_BLUE, "SANE_FRAME_BLUE" }, - { -1, NULL} - }; - static char *unknown_string = NULL; - int i; - - for (i = 0; frame_names[i].name != NULL && frame_names[i].frame != frame; i++); - - if (frame_names[i].name == NULL) { - g_free (unknown_string); - unknown_string = g_strdup_printf ("SANE_FRAME(%d)", frame); - return unknown_string; /* Note result is undefined on second call to this function */ - } - - return frame_names[i].name; -} - - -static void -do_redetect (Scanner *scanner) -{ - const SANE_Device **device_list, **device_iter; - SANE_Status status; - GList *devices = NULL; - - status = sane_get_devices (&device_list, SANE_FALSE); - g_debug ("sane_get_devices () -> %s", get_status_string (status)); - if (status != SANE_STATUS_GOOD) { - g_warning ("Unable to get SANE devices: %s", sane_strstatus(status)); - scanner->priv->state = STATE_IDLE; - return; - } - - for (device_iter = device_list; *device_iter; device_iter++) { - const SANE_Device *device = *device_iter; - ScanDevice *scan_device; - gchar *c, *label; - - g_debug ("Device: name=\"%s\" vendor=\"%s\" model=\"%s\" type=\"%s\"", - device->name, device->vendor, device->model, device->type); - - scan_device = g_malloc0 (sizeof (ScanDevice)); - - scan_device->name = g_strdup (device->name); - - /* Abbreviate HP as it is a long string and does not match what is on the physical scanner */ - if (strcmp (device->vendor, "Hewlett-Packard") == 0) - label = g_strdup_printf ("HP %s", device->model); - else - label = g_strdup_printf ("%s %s", device->vendor, device->model); - - /* Replace underscored in name */ - for (c = label; *c; c++) - if (*c == '_') - *c = ' '; - - scan_device->label = label; - - devices = g_list_append (devices, scan_device); - } - - /* Sort devices by priority */ - devices = g_list_sort (devices, (GCompareFunc) compare_devices); - - scanner->priv->redetect = FALSE; - scanner->priv->state = STATE_IDLE; - - g_free (scanner->priv->default_device); - if (devices) { - ScanDevice *device = g_list_nth_data (devices, 0); - scanner->priv->default_device = g_strdup (device->name); - } - else - scanner->priv->default_device = NULL; - - emit_signal (scanner, UPDATE_DEVICES, devices); -} - - -static gboolean -control_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int index, SANE_Action action, void *value) -{ - SANE_Status status; - gchar *old_value; - - switch (option->type) { - case SANE_TYPE_BOOL: - old_value = g_strdup_printf (*((SANE_Bool *) value) ? "SANE_TRUE" : "SANE_FALSE"); - break; - case SANE_TYPE_INT: - old_value = g_strdup_printf ("%d", *((SANE_Int *) value)); - break; - case SANE_TYPE_FIXED: - old_value = g_strdup_printf ("%f", SANE_UNFIX (*((SANE_Fixed *) value))); - break; - case SANE_TYPE_STRING: - old_value = g_strdup_printf ("\"%s\"", (char *) value); - break; - default: - old_value = g_strdup ("?"); - break; - } - - status = sane_control_option (handle, index, action, value, NULL); - switch (option->type) { - case SANE_TYPE_BOOL: - g_debug ("sane_control_option (%d, %s, %s) -> (%s, %s)", - index, get_action_string (action), - *((SANE_Bool *) value) ? "SANE_TRUE" : "SANE_FALSE", - get_status_string (status), - old_value); - break; - case SANE_TYPE_INT: - g_debug ("sane_control_option (%d, %s, %d) -> (%s, %s)", - index, get_action_string (action), - *((SANE_Int *) value), - get_status_string (status), - old_value); - break; - case SANE_TYPE_FIXED: - g_debug ("sane_control_option (%d, %s, %f) -> (%s, %s)", - index, get_action_string (action), - SANE_UNFIX (*((SANE_Fixed *) value)), - get_status_string (status), - old_value); - break; - case SANE_TYPE_STRING: - g_debug ("sane_control_option (%d, %s, \"%s\") -> (%s, %s)", - index, get_action_string (action), - (char *) value, - get_status_string (status), - old_value); - break; - default: - break; - } - g_free (old_value); - - if (status != SANE_STATUS_GOOD) - g_warning ("Error setting option %s: %s", option->name, sane_strstatus(status)); - - return status == SANE_STATUS_GOOD; -} - - -static gboolean -set_default_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index) -{ - SANE_Status status; - - /* Check if supports automatic option */ - if ((option->cap & SANE_CAP_AUTOMATIC) == 0) - return FALSE; - - status = sane_control_option (handle, option_index, SANE_ACTION_SET_AUTO, NULL, NULL); - g_debug ("sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s", - option_index, get_status_string (status)); - if (status != SANE_STATUS_GOOD) - g_warning ("Error setting default option %s: %s", option->name, sane_strstatus(status)); - - return status == SANE_STATUS_GOOD; -} - - -static void -set_bool_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, SANE_Bool value, SANE_Bool *result) -{ - SANE_Bool v = value; - g_return_if_fail (option->type == SANE_TYPE_BOOL); - control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, &v); - if (result) - *result = v; -} - - -static void -set_int_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, SANE_Int value, SANE_Int *result) -{ - SANE_Int v = value; - - g_return_if_fail (option->type == SANE_TYPE_INT); - - if (option->constraint_type == SANE_CONSTRAINT_RANGE) { - if (option->constraint.range->quant) - v *= option->constraint.range->quant; - if (v < option->constraint.range->min) - v = option->constraint.range->min; - if (v > option->constraint.range->max) - v = option->constraint.range->max; - } - else if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) { - int i; - SANE_Int distance = INT_MAX, nearest = 0; - - /* Find nearest value to requested */ - for (i = 0; i < option->constraint.word_list[0]; i++) { - SANE_Int x = option->constraint.word_list[i+1]; - if (abs (x - v) < distance) { - distance = abs (x - v); - nearest = x; - } - } - v = nearest; - } - - control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, &v); - if (result) - *result = v; -} - - -static void -set_fixed_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, gdouble value, gdouble *result) -{ - gdouble v = value; - SANE_Fixed v_fixed; - - g_return_if_fail (option->type == SANE_TYPE_FIXED); - - if (option->constraint_type == SANE_CONSTRAINT_RANGE) { - double min = SANE_UNFIX (option->constraint.range->min); - double max = SANE_UNFIX (option->constraint.range->max); - - if (v < min) - v = min; - if (v > max) - v = max; - } - else if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) { - int i; - double distance = DBL_MAX, nearest = 0.0; - - /* Find nearest value to requested */ - for (i = 0; i < option->constraint.word_list[0]; i++) { - double x = SANE_UNFIX (option->constraint.word_list[i+1]); - if (fabs (x - v) < distance) { - distance = fabs (x - v); - nearest = x; - } - } - v = nearest; - } - - v_fixed = SANE_FIX (v); - control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, &v_fixed); - if (result) - *result = SANE_UNFIX (v_fixed); -} - - -static gboolean -set_string_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, const char *value, char **result) -{ - char *string; - gsize value_size, size; - gboolean error; - - g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE); - - value_size = strlen (value) + 1; - size = option->size > value_size ? option->size : value_size; - string = g_malloc(sizeof(char) * size); - strcpy (string, value); - error = control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, string); - if (result) - *result = string; - else - g_free (string); - - return error; -} - - -static gboolean -set_constrained_string_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, const char *values[], char **result) -{ - gint i, j; - - g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE); - g_return_val_if_fail (option->constraint_type == SANE_CONSTRAINT_STRING_LIST, FALSE); - - for (i = 0; values[i] != NULL; i++) { - for (j = 0; option->constraint.string_list[j]; j++) { - if (strcmp (values[i], option->constraint.string_list[j]) == 0) - break; - } - - if (option->constraint.string_list[j] != NULL) - return set_string_option (handle, option, option_index, values[i], result); - } - - return FALSE; -} - - -static void -log_option (SANE_Int index, const SANE_Option_Descriptor *option) -{ - GString *string; - SANE_Word i; - SANE_Int cap; - - string = g_string_new (""); - - g_string_append_printf (string, "Option %d:", index); - - if (option->name) - g_string_append_printf (string, " name='%s'", option->name); - - if (option->title) - g_string_append_printf (string, " title='%s'", option->title); - - switch (option->type) { - case SANE_TYPE_BOOL: - g_string_append (string, " type=bool"); - break; - case SANE_TYPE_INT: - g_string_append (string, " type=int"); - break; - case SANE_TYPE_FIXED: - g_string_append (string, " type=fixed"); - break; - case SANE_TYPE_STRING: - g_string_append (string, " type=string"); - break; - case SANE_TYPE_BUTTON: - g_string_append (string, " type=button"); - break; - case SANE_TYPE_GROUP: - g_string_append (string, " type=group"); - break; - default: - g_string_append_printf (string, " type=%d", option->type); - break; - } - - g_string_append_printf (string, " size=%d", option->size); - - switch (option->unit) { - case SANE_UNIT_NONE: - break; - case SANE_UNIT_PIXEL: - g_string_append (string, " unit=pixels"); - break; - case SANE_UNIT_BIT: - g_string_append (string, " unit=bits"); - break; - case SANE_UNIT_MM: - g_string_append (string, " unit=mm"); - break; - case SANE_UNIT_DPI: - g_string_append (string, " unit=dpi"); - break; - case SANE_UNIT_PERCENT: - g_string_append (string, " unit=percent"); - break; - case SANE_UNIT_MICROSECOND: - g_string_append (string, " unit=microseconds"); - break; - default: - g_string_append_printf (string, " unit=%d", option->unit); - break; - } - - switch (option->constraint_type) { - case SANE_CONSTRAINT_RANGE: - if (option->type == SANE_TYPE_FIXED) - g_string_append_printf (string, " min=%f, max=%f, quant=%d", - SANE_UNFIX (option->constraint.range->min), SANE_UNFIX (option->constraint.range->max), - option->constraint.range->quant); - else - g_string_append_printf (string, " min=%d, max=%d, quant=%d", - option->constraint.range->min, option->constraint.range->max, - option->constraint.range->quant); - break; - case SANE_CONSTRAINT_WORD_LIST: - g_string_append (string, " values=["); - for (i = 0; i < option->constraint.word_list[0]; i++) { - if (i != 0) - g_string_append (string, ", "); - if (option->type == SANE_TYPE_INT) - g_string_append_printf (string, "%d", option->constraint.word_list[i+1]); - else - g_string_append_printf (string, "%f", SANE_UNFIX (option->constraint.word_list[i+1])); - } - g_string_append (string, "]"); - break; - case SANE_CONSTRAINT_STRING_LIST: - g_string_append (string, " values=["); - for (i = 0; option->constraint.string_list[i]; i++) { - if (i != 0) - g_string_append (string, ", "); - g_string_append_printf (string, "\"%s\"", option->constraint.string_list[i]); - } - g_string_append (string, "]"); - break; - default: - break; - } - - cap = option->cap; - if (cap) { - struct { - SANE_Int cap; - const char *name; - } caps[] = { - { SANE_CAP_SOFT_SELECT, "soft-select"}, - { SANE_CAP_HARD_SELECT, "hard-select"}, - { SANE_CAP_SOFT_DETECT, "soft-detect"}, - { SANE_CAP_EMULATED, "emulated"}, - { SANE_CAP_AUTOMATIC, "automatic"}, - { SANE_CAP_INACTIVE, "inactive"}, - { SANE_CAP_ADVANCED, "advanced"}, - { 0, NULL} - }; - int i, n = 0; - - g_string_append (string, " cap="); - for (i = 0; caps[i].cap > 0; i++) { - if (cap & caps[i].cap) { - cap &= ~caps[i].cap; - if (n != 0) - g_string_append (string, ","); - g_string_append (string, caps[i].name); - n++; - } - } - /* Unknown capabilities */ - if (cap) { - if (n != 0) - g_string_append (string, ","); - g_string_append_printf (string, "%x", cap); - } - } - - g_debug ("%s", string->str); - g_string_free (string, TRUE); - - if (option->desc) - g_debug (" Description: %s", option->desc); -} - - -static void -authorization_cb (SANE_String_Const resource, SANE_Char username[SANE_MAX_USERNAME_LEN], SANE_Char password[SANE_MAX_PASSWORD_LEN]) -{ - Scanner *scanner; - Credentials *credentials; - - scanner = g_hash_table_lookup (scanners, g_thread_self ()); - - emit_signal (scanner, AUTHORIZE, g_strdup (resource)); - - credentials = g_async_queue_pop (scanner->priv->authorize_queue); - strncpy (username, credentials->username, SANE_MAX_USERNAME_LEN); - strncpy (password, credentials->password, SANE_MAX_PASSWORD_LEN); - g_free (credentials); -} - - -void -scanner_authorize (Scanner *scanner, const gchar *username, const gchar *password) -{ - Credentials *credentials; - - credentials = g_malloc (sizeof (Credentials)); - credentials->username = g_strdup (username); - credentials->password = g_strdup (password); - g_async_queue_push (scanner->priv->authorize_queue, credentials); -} - - -static void -close_device (Scanner *scanner) -{ - GList *iter; - - if (scanner->priv->handle) { - sane_cancel (scanner->priv->handle); - g_debug ("sane_cancel ()"); - - sane_close (scanner->priv->handle); - g_debug ("sane_close ()"); - scanner->priv->handle = NULL; - } - - g_free (scanner->priv->buffer); - scanner->priv->buffer = NULL; - - for (iter = scanner->priv->job_queue; iter; iter = iter->next) { - ScanJob *job = (ScanJob *) iter->data; - g_free (job->device); - g_free (job); - } - g_list_free (scanner->priv->job_queue); - scanner->priv->job_queue = NULL; - - set_scanning (scanner, FALSE); -} - -static void -fail_scan (Scanner *scanner, gint error_code, const gchar *error_string) -{ - close_device (scanner); - scanner->priv->state = STATE_IDLE; - emit_signal (scanner, SCAN_FAILED, g_error_new (SCANNER_TYPE, error_code, "%s", error_string)); -} - - -static gboolean -handle_requests (Scanner *scanner) -{ - gint request_count = 0; - - /* Redetect when idle */ - if (scanner->priv->state == STATE_IDLE && scanner->priv->redetect) - scanner->priv->state = STATE_REDETECT; - - /* Process all requests */ - while (TRUE) { - ScanRequest *request = NULL; - - if ((scanner->priv->state == STATE_IDLE && request_count == 0) || - g_async_queue_length (scanner->priv->scan_queue) > 0) - request = g_async_queue_pop (scanner->priv->scan_queue); - else - return TRUE; - - g_debug ("Processing request"); - request_count++; - - switch (request->type) { - case REQUEST_REDETECT: - break; - - case REQUEST_START_SCAN: - scanner->priv->job_queue = g_list_append (scanner->priv->job_queue, request->job); - break; - - case REQUEST_CANCEL: - fail_scan (scanner, SANE_STATUS_CANCELLED, "Scan cancelled - do not report this error"); - break; - - case REQUEST_QUIT: - close_device (scanner); - g_free (request); - return FALSE; - } - - g_free (request); - } - - return TRUE; -} - - -static void -do_open (Scanner *scanner) -{ - SANE_Status status; - ScanJob *job; - - job = (ScanJob *) scanner->priv->job_queue->data; - - scanner->priv->line_count = 0; - scanner->priv->pass_number = 0; - scanner->priv->page_number = 0; - scanner->priv->notified_page = -1; - scanner->priv->option_index = 0; - scanner->priv->br_x_option_index = 0; - scanner->priv->br_y_option_index = 0; - - if (!job->device && scanner->priv->default_device) - job->device = g_strdup (scanner->priv->default_device); - - if (!job->device) { - g_warning ("No scan device available"); - fail_scan (scanner, 0, - /* Error displayed when no scanners to scan with */ - _("No scanners available. Please connect a scanner.")); - return; - } - - /* See if we can use the already open device */ - if (scanner->priv->handle) { - if (strcmp (scanner->priv->current_device, job->device) == 0) { - scanner->priv->state = STATE_GET_OPTION; - return; - } - - sane_close (scanner->priv->handle); - g_debug ("sane_close ()"); - scanner->priv->handle = NULL; - } - - g_free (scanner->priv->current_device); - scanner->priv->current_device = NULL; - - status = sane_open (job->device, &scanner->priv->handle); - g_debug ("sane_open (\"%s\") -> %s", job->device, get_status_string (status)); - - if (status != SANE_STATUS_GOOD) { - g_warning ("Unable to get open device: %s", sane_strstatus (status)); - scanner->priv->handle = NULL; - fail_scan (scanner, status, - /* Error displayed when cannot connect to scanner */ - _("Unable to connect to scanner")); - return; - } - - scanner->priv->current_device = g_strdup (job->device); - scanner->priv->state = STATE_GET_OPTION; -} - - -static void -do_get_option (Scanner *scanner) -{ - const SANE_Option_Descriptor *option; - SANE_Int option_index; - ScanJob *job; - - job = (ScanJob *) scanner->priv->job_queue->data; - - option = sane_get_option_descriptor (scanner->priv->handle, scanner->priv->option_index); - g_debug ("sane_get_option_descriptor (%d)", scanner->priv->option_index); - option_index = scanner->priv->option_index; - scanner->priv->option_index++; - - if (!option) { - /* Always use maximum scan area - some scanners default to using partial areas. This should be patched in sane-backends */ - if (scanner->priv->br_x_option_index) { - option = sane_get_option_descriptor (scanner->priv->handle, scanner->priv->br_x_option_index); - g_debug ("sane_get_option_descriptor (%d)", scanner->priv->br_x_option_index); - if (option->constraint_type == SANE_CONSTRAINT_RANGE) { - if (option->type == SANE_TYPE_FIXED) - set_fixed_option (scanner->priv->handle, option, scanner->priv->br_x_option_index, SANE_UNFIX (option->constraint.range->max), NULL); - else - set_int_option (scanner->priv->handle, option, scanner->priv->br_x_option_index, option->constraint.range->max, NULL); - } - } - if (scanner->priv->br_y_option_index) { - option = sane_get_option_descriptor (scanner->priv->handle, scanner->priv->br_y_option_index); - g_debug ("sane_get_option_descriptor (%d)", scanner->priv->br_y_option_index); - if (option->constraint_type == SANE_CONSTRAINT_RANGE) { - if (option->type == SANE_TYPE_FIXED) - set_fixed_option (scanner->priv->handle, option, scanner->priv->br_y_option_index, SANE_UNFIX (option->constraint.range->max), NULL); - else - set_int_option (scanner->priv->handle, option, scanner->priv->br_y_option_index, option->constraint.range->max, NULL); - } - } - - scanner->priv->state = STATE_START; - return; - } - - log_option (option_index, option); - - /* Ignore groups */ - if (option->type == SANE_TYPE_GROUP) - return; - - /* Option disabled */ - if (option->cap & SANE_CAP_INACTIVE) - return; - - /* Some options are unnammed (e.g. Option 0) */ - if (option->name == NULL) - return; - - if (strcmp (option->name, SANE_NAME_SCAN_RESOLUTION) == 0) { - if (option->type == SANE_TYPE_FIXED) { - set_fixed_option (scanner->priv->handle, option, option_index, job->dpi, &job->dpi); - } - else { - SANE_Int dpi; - set_int_option (scanner->priv->handle, option, option_index, job->dpi, &dpi); - job->dpi = dpi; - } - } - else if (strcmp (option->name, SANE_NAME_SCAN_SOURCE) == 0) { - const char *flatbed_sources[] = - { - "Auto", - SANE_I18N ("Auto"), - "Flatbed", - SANE_I18N ("Flatbed"), - "FlatBed", - "Normal", - SANE_I18N ("Normal"), - NULL - }; - - const char *adf_sources[] = - { - "Automatic Document Feeder", - SANE_I18N ("Automatic Document Feeder"), - "ADF", - "Automatic Document Feeder(left aligned)", /* Seen in the proprietary brother3 driver */ - "Automatic Document Feeder(centrally aligned)", /* Seen in the proprietary brother3 driver */ - NULL - }; - - const char *adf_front_sources[] = - { - "ADF Front", - SANE_I18N ("ADF Front"), - NULL - }; - - const char *adf_back_sources[] = - { - "ADF Back", - SANE_I18N ("ADF Back"), - NULL - }; - - const char *adf_duplex_sources[] = - { - "ADF Duplex", - SANE_I18N ("ADF Duplex"), - NULL - }; - - switch (job->type) { - case SCAN_SINGLE: - if (!set_default_option (scanner->priv->handle, option, option_index)) - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, flatbed_sources, NULL)) - g_warning ("Unable to set single page source, please file a bug"); - break; - case SCAN_ADF_FRONT: - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_front_sources, NULL)) - if (!!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_sources, NULL)) - g_warning ("Unable to set front ADF source, please file a bug"); - break; - case SCAN_ADF_BACK: - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_back_sources, NULL)) - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_sources, NULL)) - g_warning ("Unable to set back ADF source, please file a bug"); - break; - case SCAN_ADF_BOTH: - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_duplex_sources, NULL)) - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_sources, NULL)) - g_warning ("Unable to set duplex ADF source, please file a bug"); - break; - } - } - else if (strcmp (option->name, "duplex") == 0) { - if (option->type == SANE_TYPE_BOOL) - set_bool_option (scanner->priv->handle, option, option_index, job->type == SCAN_ADF_BOTH, NULL); - } - else if (strcmp (option->name, "batch-scan") == 0) { - if (option->type == SANE_TYPE_BOOL) - set_bool_option (scanner->priv->handle, option, option_index, job->type != SCAN_SINGLE, NULL); - } - else if (strcmp (option->name, SANE_NAME_BIT_DEPTH) == 0) { - if (job->depth > 0) - set_int_option (scanner->priv->handle, option, option_index, job->depth, NULL); - } - else if (strcmp (option->name, SANE_NAME_SCAN_MODE) == 0) { - /* The names of scan modes often used in drivers, as taken from the sane-backends source */ - const char *color_scan_modes[] = - { - SANE_VALUE_SCAN_MODE_COLOR, - "Color", - "24bit Color", /* Seen in the proprietary brother3 driver */ - NULL - }; - const char *gray_scan_modes[] = - { - SANE_VALUE_SCAN_MODE_GRAY, - "Gray", - "Grayscale", - SANE_I18N ("Grayscale"), - "True Gray", /* Seen in the proprietary brother3 driver */ - NULL - }; - const char *lineart_scan_modes[] = - { - SANE_VALUE_SCAN_MODE_LINEART, - "Lineart", - "LineArt", - SANE_I18N ("LineArt"), - "Black & White", - SANE_I18N ("Black & White"), - "Binary", - SANE_I18N ("Binary"), - "Thresholded", - SANE_VALUE_SCAN_MODE_GRAY, - "Gray", - "Grayscale", - SANE_I18N ("Grayscale"), - "True Gray", /* Seen in the proprietary brother3 driver */ - NULL - }; - - switch (job->scan_mode) { - case SCAN_MODE_COLOR: - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, color_scan_modes, NULL)) - g_warning ("Unable to set Color mode, please file a bug"); - break; - case SCAN_MODE_GRAY: - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, gray_scan_modes, NULL)) - g_warning ("Unable to set Gray mode, please file a bug"); - break; - case SCAN_MODE_LINEART: - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, lineart_scan_modes, NULL)) - g_warning ("Unable to set Lineart mode, please file a bug"); - break; - default: - break; - } - } - /* Disable compression, we will compress after scanning */ - else if (strcmp (option->name, "compression") == 0) { - const char *disable_compression_names[] = - { - SANE_I18N ("None"), - SANE_I18N ("none"), - "None", - "none", - NULL - }; - - if (!set_constrained_string_option (scanner->priv->handle, option, option_index, disable_compression_names, NULL)) - g_warning ("Unable to disable compression, please file a bug"); - } - else if (strcmp (option->name, SANE_NAME_SCAN_BR_X) == 0) - scanner->priv->br_x_option_index = option_index; - else if (strcmp (option->name, SANE_NAME_SCAN_BR_Y) == 0) - scanner->priv->br_y_option_index = option_index; - else if (strcmp (option->name, SANE_NAME_PAGE_WIDTH) == 0) { - if (job->page_width > 0.0) { - if (option->type == SANE_TYPE_FIXED) - set_fixed_option (scanner->priv->handle, option, option_index, job->page_width / 10.0, NULL); - else - set_int_option (scanner->priv->handle, option, option_index, job->page_width / 10, NULL); - } - } - else if (strcmp (option->name, SANE_NAME_PAGE_HEIGHT) == 0) { - if (job->page_height > 0.0) { - if (option->type == SANE_TYPE_FIXED) - set_fixed_option (scanner->priv->handle, option, option_index, job->page_height / 10.0, NULL); - else - set_int_option (scanner->priv->handle, option, option_index, job->page_height / 10, NULL); - } - } - - /* Test scanner options (hoping will not effect other scanners...) */ - if (strcmp (scanner->priv->current_device, "test") == 0) { - if (strcmp (option->name, "hand-scanner") == 0) { - set_bool_option (scanner->priv->handle, option, option_index, FALSE, NULL); - } - else if (strcmp (option->name, "three-pass") == 0) { - set_bool_option (scanner->priv->handle, option, option_index, FALSE, NULL); - } - else if (strcmp (option->name, "test-picture") == 0) { - set_string_option (scanner->priv->handle, option, option_index, "Color pattern", NULL); - } - else if (strcmp (option->name, "read-delay") == 0) { - set_bool_option (scanner->priv->handle, option, option_index, TRUE, NULL); - } - else if (strcmp (option->name, "read-delay-duration") == 0) { - set_int_option (scanner->priv->handle, option, option_index, 200000, NULL); - } - } -} - - -static void -do_complete_document (Scanner *scanner) -{ - ScanJob *job; - - job = (ScanJob *) scanner->priv->job_queue->data; - g_free (job->device); - g_free (job); - scanner->priv->job_queue = g_list_remove_link (scanner->priv->job_queue, scanner->priv->job_queue); - - scanner->priv->state = STATE_IDLE; - - /* Continue onto the next job */ - if (scanner->priv->job_queue) { - scanner->priv->state = STATE_OPEN; - return; - } - - /* Trigger timeout to close */ - // TODO - - emit_signal (scanner, DOCUMENT_DONE, NULL); - set_scanning (scanner, FALSE); -} - - -static void -do_start (Scanner *scanner) -{ - SANE_Status status; - - emit_signal (scanner, EXPECT_PAGE, NULL); - - status = sane_start (scanner->priv->handle); - g_debug ("sane_start (page=%d, pass=%d) -> %s", scanner->priv->page_number, scanner->priv->pass_number, get_status_string (status)); - if (status == SANE_STATUS_GOOD) { - scanner->priv->state = STATE_GET_PARAMETERS; - } - else if (status == SANE_STATUS_NO_DOCS) { - do_complete_document (scanner); - } - else { - g_warning ("Unable to start device: %s", sane_strstatus (status)); - fail_scan (scanner, status, - /* Error display when unable to start scan */ - _("Unable to start scan")); - } -} - - -static void -do_get_parameters (Scanner *scanner) -{ - SANE_Status status; - ScanPageInfo *info; - ScanJob *job; - - status = sane_get_parameters (scanner->priv->handle, &scanner->priv->parameters); - g_debug ("sane_get_parameters () -> %s", get_status_string (status)); - if (status != SANE_STATUS_GOOD) { - g_warning ("Unable to get device parameters: %s", sane_strstatus (status)); - fail_scan (scanner, status, - /* Error displayed when communication with scanner broken */ - _("Error communicating with scanner")); - return; - } - - job = (ScanJob *) scanner->priv->job_queue->data; - - g_debug ("Parameters: format=%s last_frame=%s bytes_per_line=%d pixels_per_line=%d lines=%d depth=%d", - get_frame_string (scanner->priv->parameters.format), - scanner->priv->parameters.last_frame ? "SANE_TRUE" : "SANE_FALSE", - scanner->priv->parameters.bytes_per_line, - scanner->priv->parameters.pixels_per_line, - scanner->priv->parameters.lines, - scanner->priv->parameters.depth); - - info = g_malloc(sizeof(ScanPageInfo)); - info->width = scanner->priv->parameters.pixels_per_line; - info->height = scanner->priv->parameters.lines; - info->depth = scanner->priv->parameters.depth; - /* Reduce bit depth if requested lower than received */ - // FIXME: This a hack and only works on 8 bit gray to 2 bit gray - if (scanner->priv->parameters.depth == 8 && scanner->priv->parameters.format == SANE_FRAME_GRAY && job->depth == 2 && job->scan_mode == SCAN_MODE_GRAY) - info->depth = job->depth; - info->n_channels = scanner->priv->parameters.format == SANE_FRAME_GRAY ? 1 : 3; - info->dpi = job->dpi; // FIXME: This is the requested DPI, not the actual DPI - info->device = g_strdup (scanner->priv->current_device); - - if (scanner->priv->page_number != scanner->priv->notified_page) { - emit_signal (scanner, GOT_PAGE_INFO, info); - scanner->priv->notified_page = scanner->priv->page_number; - } - - /* Prepare for read */ - scanner->priv->buffer_size = scanner->priv->parameters.bytes_per_line + 1; /* Use +1 so buffer is not resized if driver returns one line per read */ - scanner->priv->buffer = g_malloc (sizeof(SANE_Byte) * scanner->priv->buffer_size); - scanner->priv->n_used = 0; - scanner->priv->line_count = 0; - scanner->priv->pass_number = 0; - scanner->priv->state = STATE_READ; -} - - -static void -do_complete_page (Scanner *scanner) -{ - ScanJob *job; - - emit_signal (scanner, PAGE_DONE, NULL); - - job = (ScanJob *) scanner->priv->job_queue->data; - - /* If multi-pass then scan another page */ - if (!scanner->priv->parameters.last_frame) { - scanner->priv->pass_number++; - scanner->priv->state = STATE_START; - return; - } - - /* Go back for another page */ - if (job->type != SCAN_SINGLE) { - scanner->priv->page_number++; - scanner->priv->pass_number = 0; - emit_signal (scanner, PAGE_DONE, NULL); - scanner->priv->state = STATE_START; - return; - } - - sane_cancel (scanner->priv->handle); - g_debug ("sane_cancel ()"); - - do_complete_document (scanner); -} - - -static void -do_read (Scanner *scanner) -{ - ScanJob *job; - SANE_Status status; - SANE_Int n_to_read, n_read; - gboolean full_read = FALSE; - - job = (ScanJob *) scanner->priv->job_queue->data; - - /* Read as many bytes as we expect */ - n_to_read = scanner->priv->buffer_size - scanner->priv->n_used; - - status = sane_read (scanner->priv->handle, - scanner->priv->buffer + scanner->priv->n_used, - n_to_read, &n_read); - g_debug ("sane_read (%d) -> (%s, %d)", n_to_read, get_status_string (status), n_read); - - /* Completed read */ - if (status == SANE_STATUS_EOF) { - if (scanner->priv->parameters.lines > 0 && scanner->priv->line_count != scanner->priv->parameters.lines) - g_warning ("Scan completed with %d lines, expected %d lines", scanner->priv->parameters.lines, scanner->priv->parameters.lines); - if (scanner->priv->n_used > 0) - g_warning ("Scan complete with %d bytes of unused data", scanner->priv->n_used); - do_complete_page (scanner); - return; - } - - /* Communication error */ - if (status != SANE_STATUS_GOOD) { - g_warning ("Unable to read frame from device: %s", sane_strstatus (status)); - fail_scan (scanner, status, - /* Error displayed when communication with scanner broken */ - _("Error communicating with scanner")); - return; - } - - if (scanner->priv->n_used == 0 && n_read == scanner->priv->buffer_size) - full_read = TRUE; - scanner->priv->n_used += n_read; - - /* Feed out lines */ - if (scanner->priv->n_used >= scanner->priv->parameters.bytes_per_line) { - ScanLine *line; - int i, n_remaining; - - line = g_malloc(sizeof(ScanLine)); - switch (scanner->priv->parameters.format) { - case SANE_FRAME_GRAY: - line->channel = 0; - break; - case SANE_FRAME_RGB: - line->channel = -1; - break; - case SANE_FRAME_RED: - line->channel = 0; - break; - case SANE_FRAME_GREEN: - line->channel = 1; - break; - case SANE_FRAME_BLUE: - line->channel = 2; - break; - } - line->width = scanner->priv->parameters.pixels_per_line; - line->depth = scanner->priv->parameters.depth; - line->data = scanner->priv->buffer; - line->data_length = scanner->priv->parameters.bytes_per_line; - line->number = scanner->priv->line_count; - line->n_lines = scanner->priv->n_used / line->data_length; - - scanner->priv->buffer = NULL; - scanner->priv->line_count += line->n_lines; - - /* Increase buffer size if did full read */ - if (full_read) - scanner->priv->buffer_size += scanner->priv->parameters.bytes_per_line; - - scanner->priv->buffer = g_malloc(sizeof(SANE_Byte) * scanner->priv->buffer_size); - n_remaining = scanner->priv->n_used - (line->n_lines * line->data_length); - scanner->priv->n_used = 0; - for (i = 0; i < n_remaining; i++) { - scanner->priv->buffer[i] = line->data[i + (line->n_lines * line->data_length)]; - scanner->priv->n_used++; - } - - /* Reduce bit depth if requested lower than received */ - // FIXME: This a hack and only works on 8 bit gray to 2 bit gray - if (scanner->priv->parameters.depth == 8 && scanner->priv->parameters.format == SANE_FRAME_GRAY && - job->depth == 2 && job->scan_mode == SCAN_MODE_GRAY) { - gint block_shift = 6; - guchar block = 0; - guchar *write_ptr = line->data; - - for (i = 0; i < line->n_lines; i++) { - guchar *in_line = line->data + i * line->data_length; - gint x; - - for (x = 0; x < line->width; x++) { - guchar *p = in_line + x; - guchar sample; - - if (p[0] >= 192) - sample = 3; - else if (p[0] >= 128) - sample = 2; - else if (p[0] >= 64) - sample = 1; - else - sample = 0; - - block |= sample << block_shift; - if (block_shift == 0) { - *write_ptr = block; - write_ptr++; - block = 0; - block_shift = 6; - } - else { - block_shift -= 2; - } - } - - /* Finish each line on a byte boundary */ - if (block_shift != 6) { - *write_ptr = block; - write_ptr++; - block = 0; - block_shift = 6; - } - } - - line->data_length = (line->width * 2 + 7) / 8; - } - - emit_signal (scanner, GOT_LINE, line); - } -} - - -static gpointer -scan_thread (Scanner *scanner) -{ - SANE_Status status; - SANE_Int version_code; - - g_hash_table_insert (scanners, g_thread_self (), scanner); - - scanner->priv->state = STATE_IDLE; - - status = sane_init (&version_code, authorization_cb); - g_debug ("sane_init () -> %s", get_status_string (status)); - if (status != SANE_STATUS_GOOD) { - g_warning ("Unable to initialize SANE backend: %s", sane_strstatus(status)); - return FALSE; - } - g_debug ("SANE version %d.%d.%d", - SANE_VERSION_MAJOR(version_code), - SANE_VERSION_MINOR(version_code), - SANE_VERSION_BUILD(version_code)); - - /* Scan for devices on first start */ - scanner_redetect (scanner); - - while (handle_requests (scanner)) { - switch (scanner->priv->state) { - case STATE_IDLE: - if (scanner->priv->job_queue) { - set_scanning (scanner, TRUE); - scanner->priv->state = STATE_OPEN; - } - break; - case STATE_REDETECT: - do_redetect (scanner); - break; - case STATE_OPEN: - do_open (scanner); - break; - case STATE_GET_OPTION: - do_get_option (scanner); - break; - case STATE_START: - do_start (scanner); - break; - case STATE_GET_PARAMETERS: - do_get_parameters (scanner); - break; - case STATE_READ: - do_read (scanner); - break; - } - } - - return NULL; -} - - -Scanner * -scanner_new () -{ - return g_object_new (SCANNER_TYPE, NULL); -} - - -void -scanner_start (Scanner *scanner) -{ - GError *error = NULL; - scanner->priv->thread = g_thread_create ((GThreadFunc) scan_thread, scanner, TRUE, &error); - if (error) { - g_critical ("Unable to create thread: %s", error->message); - g_error_free (error); - } -} - - -void -scanner_redetect (Scanner *scanner) -{ - ScanRequest *request; - - if (scanner->priv->redetect) - return; - scanner->priv->redetect = TRUE; - - g_debug ("Requesting redetection of scan devices"); - - request = g_malloc0 (sizeof (ScanRequest)); - request->type = REQUEST_REDETECT; - g_async_queue_push (scanner->priv->scan_queue, request); -} - - -gboolean -scanner_is_scanning (Scanner *scanner) -{ - return scanner->priv->scanning; -} - - -void -scanner_scan (Scanner *scanner, const char *device, ScanOptions *options) -{ - ScanRequest *request; - const gchar *type_string; - - switch (options->type) { - case SCAN_SINGLE: - type_string = "SCAN_SINGLE"; - break; - case SCAN_ADF_FRONT: - type_string = "SCAN_ADF_FRONT"; - break; - case SCAN_ADF_BACK: - type_string = "SCAN_ADF_BACK"; - break; - case SCAN_ADF_BOTH: - type_string = "SCAN_ADF_BOTH"; - break; - default: - g_assert (FALSE); - return; - } - - g_debug ("scanner_scan (\"%s\", %d, %s)", device ? device : "(null)", options->dpi, type_string); - request = g_malloc0 (sizeof (ScanRequest)); - request->type = REQUEST_START_SCAN; - request->job = g_malloc0 (sizeof (ScanJob)); - request->job->device = g_strdup (device); - request->job->dpi = options->dpi; - request->job->scan_mode = options->scan_mode; - request->job->depth = options->depth; - request->job->type = options->type; - request->job->page_width = options->paper_width; - request->job->page_height = options->paper_height; - g_async_queue_push (scanner->priv->scan_queue, request); -} - - -void -scanner_cancel (Scanner *scanner) -{ - ScanRequest *request; - - request = g_malloc0 (sizeof (ScanRequest)); - request->type = REQUEST_CANCEL; - g_async_queue_push (scanner->priv->scan_queue, request); -} - - -void scanner_free (Scanner *scanner) -{ - ScanRequest *request; - - g_debug ("Stopping scan thread"); - - request = g_malloc0 (sizeof (ScanRequest)); - request->type = REQUEST_QUIT; - g_async_queue_push (scanner->priv->scan_queue, request); - - if (scanner->priv->thread) - g_thread_join (scanner->priv->thread); - - g_async_queue_unref (scanner->priv->scan_queue); - g_object_unref (scanner); - - sane_exit (); - g_debug ("sane_exit ()"); -} - - -static void -scanner_class_init (ScannerClass *klass) -{ - signals[AUTHORIZE] = - g_signal_new ("authorize", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, authorize), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - signals[UPDATE_DEVICES] = - g_signal_new ("update-devices", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, update_devices), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - signals[EXPECT_PAGE] = - g_signal_new ("expect-page", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, expect_page), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[GOT_PAGE_INFO] = - g_signal_new ("got-page-info", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, got_page_info), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - signals[GOT_LINE] = - g_signal_new ("got-line", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, got_line), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - signals[SCAN_FAILED] = - g_signal_new ("scan-failed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, scan_failed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - signals[PAGE_DONE] = - g_signal_new ("page-done", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, page_done), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[DOCUMENT_DONE] = - g_signal_new ("document-done", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, document_done), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[SCANNING_CHANGED] = - g_signal_new ("scanning-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ScannerClass, scanning_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (ScannerPrivate)); - - scanners = g_hash_table_new (g_direct_hash, g_direct_equal); -} - - -static void -scanner_init (Scanner *scanner) -{ - scanner->priv = G_TYPE_INSTANCE_GET_PRIVATE (scanner, SCANNER_TYPE, ScannerPrivate); - scanner->priv->scan_queue = g_async_queue_new (); - scanner->priv->authorize_queue = g_async_queue_new (); +struct _Notify { + GTypeInstance parent_instance; + volatile int ref_count; + NotifyPrivate * priv; +}; + +struct _NotifyClass { + GTypeClass parent_class; + void (*finalize) (Notify *self); + void (*run) (Notify* self, Scanner* scanner); +}; + +struct _ParamSpecNotify { + GParamSpec parent_instance; +}; + +struct _NotifyScanningChanged { + Notify parent_instance; + NotifyScanningChangedPrivate * priv; +}; + +struct _NotifyScanningChangedClass { + NotifyClass parent_class; +}; + +struct _NotifyUpdateDevices { + Notify parent_instance; + NotifyUpdateDevicesPrivate * priv; +}; + +struct _NotifyUpdateDevicesClass { + NotifyClass parent_class; +}; + +struct _NotifyUpdateDevicesPrivate { + GList* devices; +}; + +struct _NotifyRequestAuthorization { + Notify parent_instance; + NotifyRequestAuthorizationPrivate * priv; +}; + +struct _NotifyRequestAuthorizationClass { + NotifyClass parent_class; +}; + +struct _NotifyRequestAuthorizationPrivate { + gchar* resource; +}; + +struct _NotifyScanFailed { + Notify parent_instance; + NotifyScanFailedPrivate * priv; +}; + +struct _NotifyScanFailedClass { + NotifyClass parent_class; +}; + +struct _NotifyScanFailedPrivate { + gint error_code; + gchar* error_string; +}; + +struct _NotifyDocumentDone { + Notify parent_instance; + NotifyDocumentDonePrivate * priv; +}; + +struct _NotifyDocumentDoneClass { + NotifyClass parent_class; +}; + +struct _NotifyExpectPage { + Notify parent_instance; + NotifyExpectPagePrivate * priv; +}; + +struct _NotifyExpectPageClass { + NotifyClass parent_class; +}; + +struct _NotifyGotPageInfo { + Notify parent_instance; + NotifyGotPageInfoPrivate * priv; +}; + +struct _NotifyGotPageInfoClass { + NotifyClass parent_class; +}; + +struct _NotifyGotPageInfoPrivate { + ScanPageInfo* info; +}; + +struct _NotifyPageDone { + Notify parent_instance; + NotifyPageDonePrivate * priv; +}; + +struct _NotifyPageDoneClass { + NotifyClass parent_class; +}; + +struct _NotifyGotLine { + Notify parent_instance; + NotifyGotLinePrivate * priv; +}; + +struct _NotifyGotLineClass { + NotifyClass parent_class; +}; + +struct _NotifyGotLinePrivate { + ScanLine* line; +}; + +struct _Scanner { + GTypeInstance parent_instance; + volatile int ref_count; + ScannerPrivate * priv; +}; + +struct _ScannerClass { + GTypeClass parent_class; + void (*finalize) (Scanner *self); +}; + +struct _ScannerPrivate { + GThread* thread; + GAsyncQueue* request_queue; + GAsyncQueue* notify_queue; + GAsyncQueue* authorize_queue; + gchar* default_device; + ScanState state; + gboolean need_redetect; + GList* job_queue; + SANE_Handle handle; + gboolean have_handle; + gchar* current_device; + SANE_Parameters parameters; + SANE_Int option_index; + SANE_Int br_x_option_index; + SANE_Int br_y_option_index; + guchar* buffer; + gint buffer_length1; + gint _buffer_size_; + gint n_used; + gint line_count; + gint pass_number; + gint page_number; + gint notified_page; + gboolean scanning; +}; + +struct _ParamSpecScanner { + GParamSpec parent_instance; +}; + + +static gpointer scan_device_parent_class = NULL; +static gpointer scan_page_info_parent_class = NULL; +static gpointer scan_line_parent_class = NULL; +static gpointer scan_options_parent_class = NULL; +static gpointer scan_job_parent_class = NULL; +static gpointer request_parent_class = NULL; +static gpointer request_redetect_parent_class = NULL; +static gpointer request_cancel_parent_class = NULL; +static gpointer request_start_scan_parent_class = NULL; +static gpointer request_quit_parent_class = NULL; +static gpointer credentials_parent_class = NULL; +static gpointer notify_parent_class = NULL; +static gpointer notify_scanning_changed_parent_class = NULL; +static gpointer notify_update_devices_parent_class = NULL; +static gpointer notify_request_authorization_parent_class = NULL; +static gpointer notify_scan_failed_parent_class = NULL; +static gpointer notify_document_done_parent_class = NULL; +static gpointer notify_expect_page_parent_class = NULL; +static gpointer notify_got_page_info_parent_class = NULL; +static gpointer notify_page_done_parent_class = NULL; +static gpointer notify_got_line_parent_class = NULL; +static gpointer scanner_parent_class = NULL; +static Scanner* scanner_scanner_object; +static Scanner* scanner_scanner_object = NULL; + +gpointer scan_device_ref (gpointer instance); +void scan_device_unref (gpointer instance); +GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_device (GValue* value, gpointer v_object); +void value_take_scan_device (GValue* value, gpointer v_object); +gpointer value_get_scan_device (const GValue* value); +GType scan_device_get_type (void) G_GNUC_CONST; +enum { + SCAN_DEVICE_DUMMY_PROPERTY +}; +ScanDevice* scan_device_new (void); +ScanDevice* scan_device_construct (GType object_type); +static void scan_device_finalize (ScanDevice* obj); +gpointer scan_page_info_ref (gpointer instance); +void scan_page_info_unref (gpointer instance); +GParamSpec* param_spec_scan_page_info (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_page_info (GValue* value, gpointer v_object); +void value_take_scan_page_info (GValue* value, gpointer v_object); +gpointer value_get_scan_page_info (const GValue* value); +GType scan_page_info_get_type (void) G_GNUC_CONST; +enum { + SCAN_PAGE_INFO_DUMMY_PROPERTY +}; +ScanPageInfo* scan_page_info_new (void); +ScanPageInfo* scan_page_info_construct (GType object_type); +static void scan_page_info_finalize (ScanPageInfo* obj); +gpointer scan_line_ref (gpointer instance); +void scan_line_unref (gpointer instance); +GParamSpec* param_spec_scan_line (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_line (GValue* value, gpointer v_object); +void value_take_scan_line (GValue* value, gpointer v_object); +gpointer value_get_scan_line (const GValue* value); +GType scan_line_get_type (void) G_GNUC_CONST; +enum { + SCAN_LINE_DUMMY_PROPERTY +}; +ScanLine* scan_line_new (void); +ScanLine* scan_line_construct (GType object_type); +static void scan_line_finalize (ScanLine* obj); +GType scan_mode_get_type (void) G_GNUC_CONST; +GType scan_type_get_type (void) G_GNUC_CONST; +gpointer scan_options_ref (gpointer instance); +void scan_options_unref (gpointer instance); +GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_options (GValue* value, gpointer v_object); +void value_take_scan_options (GValue* value, gpointer v_object); +gpointer value_get_scan_options (const GValue* value); +GType scan_options_get_type (void) G_GNUC_CONST; +enum { + SCAN_OPTIONS_DUMMY_PROPERTY +}; +ScanOptions* scan_options_new (void); +ScanOptions* scan_options_construct (GType object_type); +static void scan_options_finalize (ScanOptions* obj); +gpointer scan_job_ref (gpointer instance); +void scan_job_unref (gpointer instance); +GParamSpec* param_spec_scan_job (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_job (GValue* value, gpointer v_object); +void value_take_scan_job (GValue* value, gpointer v_object); +gpointer value_get_scan_job (const GValue* value); +GType scan_job_get_type (void) G_GNUC_CONST; +enum { + SCAN_JOB_DUMMY_PROPERTY +}; +ScanJob* scan_job_new (void); +ScanJob* scan_job_construct (GType object_type); +static void scan_job_finalize (ScanJob* obj); +gpointer request_ref (gpointer instance); +void request_unref (gpointer instance); +GParamSpec* param_spec_request (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_request (GValue* value, gpointer v_object); +void value_take_request (GValue* value, gpointer v_object); +gpointer value_get_request (const GValue* value); +GType request_get_type (void) G_GNUC_CONST; +enum { + REQUEST_DUMMY_PROPERTY +}; +Request* request_new (void); +Request* request_construct (GType object_type); +static void request_finalize (Request* obj); +GType request_redetect_get_type (void) G_GNUC_CONST; +enum { + REQUEST_REDETECT_DUMMY_PROPERTY +}; +RequestRedetect* request_redetect_new (void); +RequestRedetect* request_redetect_construct (GType object_type); +GType request_cancel_get_type (void) G_GNUC_CONST; +enum { + REQUEST_CANCEL_DUMMY_PROPERTY +}; +RequestCancel* request_cancel_new (void); +RequestCancel* request_cancel_construct (GType object_type); +GType request_start_scan_get_type (void) G_GNUC_CONST; +enum { + REQUEST_START_SCAN_DUMMY_PROPERTY +}; +RequestStartScan* request_start_scan_new (void); +RequestStartScan* request_start_scan_construct (GType object_type); +static void request_start_scan_finalize (Request* obj); +GType request_quit_get_type (void) G_GNUC_CONST; +enum { + REQUEST_QUIT_DUMMY_PROPERTY +}; +RequestQuit* request_quit_new (void); +RequestQuit* request_quit_construct (GType object_type); +gpointer credentials_ref (gpointer instance); +void credentials_unref (gpointer instance); +GParamSpec* param_spec_credentials (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_credentials (GValue* value, gpointer v_object); +void value_take_credentials (GValue* value, gpointer v_object); +gpointer value_get_credentials (const GValue* value); +GType credentials_get_type (void) G_GNUC_CONST; +enum { + CREDENTIALS_DUMMY_PROPERTY +}; +Credentials* credentials_new (void); +Credentials* credentials_construct (GType object_type); +static void credentials_finalize (Credentials* obj); +GType scan_state_get_type (void) G_GNUC_CONST; +gpointer notify_ref (gpointer instance); +void notify_unref (gpointer instance); +GParamSpec* param_spec_notify (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_notify (GValue* value, gpointer v_object); +void value_take_notify (GValue* value, gpointer v_object); +gpointer value_get_notify (const GValue* value); +GType notify_get_type (void) G_GNUC_CONST; +gpointer scanner_ref (gpointer instance); +void scanner_unref (gpointer instance); +GParamSpec* param_spec_scanner (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scanner (GValue* value, gpointer v_object); +void value_take_scanner (GValue* value, gpointer v_object); +gpointer value_get_scanner (const GValue* value); +GType scanner_get_type (void) G_GNUC_CONST; +enum { + NOTIFY_DUMMY_PROPERTY +}; +void notify_run (Notify* self, Scanner* scanner); +static void notify_real_run (Notify* self, Scanner* scanner); +Notify* notify_new (void); +Notify* notify_construct (GType object_type); +static void notify_finalize (Notify* obj); +GType notify_scanning_changed_get_type (void) G_GNUC_CONST; +enum { + NOTIFY_SCANNING_CHANGED_DUMMY_PROPERTY +}; +static void notify_scanning_changed_real_run (Notify* base, Scanner* scanner); +NotifyScanningChanged* notify_scanning_changed_new (void); +NotifyScanningChanged* notify_scanning_changed_construct (GType object_type); +GType notify_update_devices_get_type (void) G_GNUC_CONST; +#define NOTIFY_UPDATE_DEVICES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevicesPrivate)) +enum { + NOTIFY_UPDATE_DEVICES_DUMMY_PROPERTY +}; +static void _scan_device_unref0_ (gpointer var); +static void _g_list_free__scan_device_unref0_ (GList* self); +NotifyUpdateDevices* notify_update_devices_new (GList* devices); +NotifyUpdateDevices* notify_update_devices_construct (GType object_type, GList* devices); +static void notify_update_devices_real_run (Notify* base, Scanner* scanner); +static void notify_update_devices_finalize (Notify* obj); +GType notify_request_authorization_get_type (void) G_GNUC_CONST; +#define NOTIFY_REQUEST_AUTHORIZATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorizationPrivate)) +enum { + NOTIFY_REQUEST_AUTHORIZATION_DUMMY_PROPERTY +}; +NotifyRequestAuthorization* notify_request_authorization_new (const gchar* resource); +NotifyRequestAuthorization* notify_request_authorization_construct (GType object_type, const gchar* resource); +static void notify_request_authorization_real_run (Notify* base, Scanner* scanner); +static void notify_request_authorization_finalize (Notify* obj); +GType notify_scan_failed_get_type (void) G_GNUC_CONST; +#define NOTIFY_SCAN_FAILED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailedPrivate)) +enum { + NOTIFY_SCAN_FAILED_DUMMY_PROPERTY +}; +NotifyScanFailed* notify_scan_failed_new (gint error_code, const gchar* error_string); +NotifyScanFailed* notify_scan_failed_construct (GType object_type, gint error_code, const gchar* error_string); +static void notify_scan_failed_real_run (Notify* base, Scanner* scanner); +static void notify_scan_failed_finalize (Notify* obj); +GType notify_document_done_get_type (void) G_GNUC_CONST; +enum { + NOTIFY_DOCUMENT_DONE_DUMMY_PROPERTY +}; +static void notify_document_done_real_run (Notify* base, Scanner* scanner); +NotifyDocumentDone* notify_document_done_new (void); +NotifyDocumentDone* notify_document_done_construct (GType object_type); +GType notify_expect_page_get_type (void) G_GNUC_CONST; +enum { + NOTIFY_EXPECT_PAGE_DUMMY_PROPERTY +}; +static void notify_expect_page_real_run (Notify* base, Scanner* scanner); +NotifyExpectPage* notify_expect_page_new (void); +NotifyExpectPage* notify_expect_page_construct (GType object_type); +GType notify_got_page_info_get_type (void) G_GNUC_CONST; +#define NOTIFY_GOT_PAGE_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfoPrivate)) +enum { + NOTIFY_GOT_PAGE_INFO_DUMMY_PROPERTY +}; +NotifyGotPageInfo* notify_got_page_info_new (ScanPageInfo* info); +NotifyGotPageInfo* notify_got_page_info_construct (GType object_type, ScanPageInfo* info); +static void notify_got_page_info_real_run (Notify* base, Scanner* scanner); +static void notify_got_page_info_finalize (Notify* obj); +GType notify_page_done_get_type (void) G_GNUC_CONST; +enum { + NOTIFY_PAGE_DONE_DUMMY_PROPERTY +}; +static void notify_page_done_real_run (Notify* base, Scanner* scanner); +NotifyPageDone* notify_page_done_new (void); +NotifyPageDone* notify_page_done_construct (GType object_type); +GType notify_got_line_get_type (void) G_GNUC_CONST; +#define NOTIFY_GOT_LINE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_GOT_LINE, NotifyGotLinePrivate)) +enum { + NOTIFY_GOT_LINE_DUMMY_PROPERTY +}; +NotifyGotLine* notify_got_line_new (ScanLine* line); +NotifyGotLine* notify_got_line_construct (GType object_type, ScanLine* line); +static void notify_got_line_real_run (Notify* base, Scanner* scanner); +static void notify_got_line_finalize (Notify* obj); +#define SCANNER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_SCANNER, ScannerPrivate)) +enum { + SCANNER_DUMMY_PROPERTY +}; +static void _scan_job_unref0_ (gpointer var); +static void _g_list_free__scan_job_unref0_ (GList* self); +static Scanner* scanner_new (void); +static Scanner* scanner_construct (GType object_type); +Scanner* scanner_get_instance (void); +static gboolean scanner_notify_idle_cb (Scanner* self); +static void scanner_notify (Scanner* self, Notify* notification); +static gboolean _scanner_notify_idle_cb_gsource_func (gpointer self); +static void scanner_set_scanning (Scanner* self, gboolean is_scanning); +static gint scanner_get_device_weight (const gchar* device); +static gint scanner_compare_devices (ScanDevice* device1, ScanDevice* device2); +static void scanner_do_redetect (Scanner* self); +static gint _scanner_compare_devices_gcompare_func (gconstpointer a, gconstpointer b); +static gboolean scanner_set_default_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index); +static void scanner_set_bool_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gboolean value, gboolean* _result_); +static void scanner_set_int_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gint value, gint* _result_); +static void scanner_set_fixed_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gdouble value, gdouble* _result_); +static gboolean scanner_set_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, const gchar* value, gchar** _result_); +static gboolean scanner_set_constrained_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gchar** values, int values_length1, gchar** _result_); +static void scanner_log_option (Scanner* self, SANE_Int index, const SANE_Option_Descriptor* option); +static void scanner_authorization_cb (const gchar* resource, gchar* username, int username_length1, gchar* password, int password_length1); +void scanner_authorize (Scanner* self, const gchar* username, const gchar* password); +static void scanner_close_device (Scanner* self); +static void scanner_fail_scan (Scanner* self, gint error_code, const gchar* error_string); +static gboolean scanner_handle_requests (Scanner* self); +static void scanner_do_open (Scanner* self); +static void scanner_do_get_option (Scanner* self); +static void scanner_do_complete_document (Scanner* self); +static void scanner_do_start (Scanner* self); +static void scanner_do_get_parameters (Scanner* self); +static void scanner_do_complete_page (Scanner* self); +static void scanner_do_read (Scanner* self); +static void* scanner_scan_thread (Scanner* self); +static void _scanner_authorization_cb_sane_authcallback (const gchar* resource, gchar* username, gchar* password); +void scanner_redetect (Scanner* self); +void scanner_start (Scanner* self); +static gpointer _scanner_scan_thread_gthread_func (gpointer self); +gboolean scanner_is_scanning (Scanner* self); +static gchar* scanner_get_scan_mode_string (Scanner* self, ScanMode mode); +static gchar* scanner_get_scan_type_string (Scanner* self, ScanType type); +void scanner_scan (Scanner* self, const gchar* device, ScanOptions* options); +void scanner_cancel (Scanner* self); +void scanner_free (Scanner* self); +static void g_cclosure_user_marshal_VOID__SCAN_PAGE_INFO (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void g_cclosure_user_marshal_VOID__SCAN_LINE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void g_cclosure_user_marshal_VOID__INT_STRING (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void scanner_finalize (Scanner* obj); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); + + +ScanDevice* scan_device_construct (GType object_type) { + ScanDevice* self = NULL; + self = (ScanDevice*) g_type_create_instance (object_type); + return self; +} + + +ScanDevice* scan_device_new (void) { + return scan_device_construct (TYPE_SCAN_DEVICE); +} + + +static void value_scan_device_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_scan_device_free_value (GValue* value) { + if (value->data[0].v_pointer) { + scan_device_unref (value->data[0].v_pointer); + } +} + + +static void value_scan_device_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = scan_device_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_scan_device_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_scan_device_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + ScanDevice* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = scan_device_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_scan_device_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + ScanDevice** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = scan_device_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecScanDevice* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_DEVICE), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_scan_device (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_DEVICE), NULL); + return value->data[0].v_pointer; +} + + +void value_set_scan_device (GValue* value, gpointer v_object) { + ScanDevice* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_DEVICE)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_DEVICE)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + scan_device_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_device_unref (old); + } +} + + +void value_take_scan_device (GValue* value, gpointer v_object) { + ScanDevice* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_DEVICE)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_DEVICE)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_device_unref (old); + } +} + + +static void scan_device_class_init (ScanDeviceClass * klass) { + scan_device_parent_class = g_type_class_peek_parent (klass); + SCAN_DEVICE_CLASS (klass)->finalize = scan_device_finalize; +} + + +static void scan_device_instance_init (ScanDevice * self) { + self->ref_count = 1; +} + + +static void scan_device_finalize (ScanDevice* obj) { + ScanDevice * self; + self = SCAN_DEVICE (obj); + _g_free0 (self->name); + _g_free0 (self->label); +} + + +GType scan_device_get_type (void) { + static volatile gsize scan_device_type_id__volatile = 0; + if (g_once_init_enter (&scan_device_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_scan_device_init, value_scan_device_free_value, value_scan_device_copy_value, value_scan_device_peek_pointer, "p", value_scan_device_collect_value, "p", value_scan_device_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ScanDeviceClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_device_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanDevice), 0, (GInstanceInitFunc) scan_device_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType scan_device_type_id; + scan_device_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanDevice", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&scan_device_type_id__volatile, scan_device_type_id); + } + return scan_device_type_id__volatile; +} + + +gpointer scan_device_ref (gpointer instance) { + ScanDevice* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void scan_device_unref (gpointer instance) { + ScanDevice* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SCAN_DEVICE_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +ScanPageInfo* scan_page_info_construct (GType object_type) { + ScanPageInfo* self = NULL; + self = (ScanPageInfo*) g_type_create_instance (object_type); + return self; +} + + +ScanPageInfo* scan_page_info_new (void) { + return scan_page_info_construct (TYPE_SCAN_PAGE_INFO); +} + + +static void value_scan_page_info_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_scan_page_info_free_value (GValue* value) { + if (value->data[0].v_pointer) { + scan_page_info_unref (value->data[0].v_pointer); + } +} + + +static void value_scan_page_info_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = scan_page_info_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_scan_page_info_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_scan_page_info_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + ScanPageInfo* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = scan_page_info_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_scan_page_info_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + ScanPageInfo** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = scan_page_info_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_scan_page_info (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecScanPageInfo* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_PAGE_INFO), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_scan_page_info (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_PAGE_INFO), NULL); + return value->data[0].v_pointer; +} + + +void value_set_scan_page_info (GValue* value, gpointer v_object) { + ScanPageInfo* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_PAGE_INFO)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_PAGE_INFO)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + scan_page_info_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_page_info_unref (old); + } +} + + +void value_take_scan_page_info (GValue* value, gpointer v_object) { + ScanPageInfo* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_PAGE_INFO)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_PAGE_INFO)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_page_info_unref (old); + } +} + + +static void scan_page_info_class_init (ScanPageInfoClass * klass) { + scan_page_info_parent_class = g_type_class_peek_parent (klass); + SCAN_PAGE_INFO_CLASS (klass)->finalize = scan_page_info_finalize; +} + + +static void scan_page_info_instance_init (ScanPageInfo * self) { + self->ref_count = 1; +} + + +static void scan_page_info_finalize (ScanPageInfo* obj) { + ScanPageInfo * self; + self = SCAN_PAGE_INFO (obj); + _g_free0 (self->device); +} + + +GType scan_page_info_get_type (void) { + static volatile gsize scan_page_info_type_id__volatile = 0; + if (g_once_init_enter (&scan_page_info_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_scan_page_info_init, value_scan_page_info_free_value, value_scan_page_info_copy_value, value_scan_page_info_peek_pointer, "p", value_scan_page_info_collect_value, "p", value_scan_page_info_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ScanPageInfoClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_page_info_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanPageInfo), 0, (GInstanceInitFunc) scan_page_info_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType scan_page_info_type_id; + scan_page_info_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanPageInfo", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&scan_page_info_type_id__volatile, scan_page_info_type_id); + } + return scan_page_info_type_id__volatile; +} + + +gpointer scan_page_info_ref (gpointer instance) { + ScanPageInfo* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void scan_page_info_unref (gpointer instance) { + ScanPageInfo* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SCAN_PAGE_INFO_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +ScanLine* scan_line_construct (GType object_type) { + ScanLine* self = NULL; + self = (ScanLine*) g_type_create_instance (object_type); + return self; +} + + +ScanLine* scan_line_new (void) { + return scan_line_construct (TYPE_SCAN_LINE); +} + + +static void value_scan_line_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_scan_line_free_value (GValue* value) { + if (value->data[0].v_pointer) { + scan_line_unref (value->data[0].v_pointer); + } +} + + +static void value_scan_line_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = scan_line_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_scan_line_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_scan_line_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + ScanLine* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = scan_line_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; } + + +static gchar* value_scan_line_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + ScanLine** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = scan_line_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_scan_line (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecScanLine* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_LINE), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_scan_line (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_LINE), NULL); + return value->data[0].v_pointer; +} + + +void value_set_scan_line (GValue* value, gpointer v_object) { + ScanLine* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_LINE)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_LINE)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + scan_line_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_line_unref (old); + } +} + + +void value_take_scan_line (GValue* value, gpointer v_object) { + ScanLine* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_LINE)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_LINE)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_line_unref (old); + } +} + + +static void scan_line_class_init (ScanLineClass * klass) { + scan_line_parent_class = g_type_class_peek_parent (klass); + SCAN_LINE_CLASS (klass)->finalize = scan_line_finalize; +} + + +static void scan_line_instance_init (ScanLine * self) { + self->ref_count = 1; +} + + +static void scan_line_finalize (ScanLine* obj) { + ScanLine * self; + self = SCAN_LINE (obj); + self->data = (g_free (self->data), NULL); +} + + +GType scan_line_get_type (void) { + static volatile gsize scan_line_type_id__volatile = 0; + if (g_once_init_enter (&scan_line_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_scan_line_init, value_scan_line_free_value, value_scan_line_copy_value, value_scan_line_peek_pointer, "p", value_scan_line_collect_value, "p", value_scan_line_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ScanLineClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_line_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanLine), 0, (GInstanceInitFunc) scan_line_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType scan_line_type_id; + scan_line_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanLine", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&scan_line_type_id__volatile, scan_line_type_id); + } + return scan_line_type_id__volatile; +} + + +gpointer scan_line_ref (gpointer instance) { + ScanLine* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void scan_line_unref (gpointer instance) { + ScanLine* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SCAN_LINE_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +GType scan_mode_get_type (void) { + static volatile gsize scan_mode_type_id__volatile = 0; + if (g_once_init_enter (&scan_mode_type_id__volatile)) { + static const GEnumValue values[] = {{SCAN_MODE_DEFAULT, "SCAN_MODE_DEFAULT", "default"}, {SCAN_MODE_COLOR, "SCAN_MODE_COLOR", "color"}, {SCAN_MODE_GRAY, "SCAN_MODE_GRAY", "gray"}, {SCAN_MODE_LINEART, "SCAN_MODE_LINEART", "lineart"}, {0, NULL, NULL}}; + GType scan_mode_type_id; + scan_mode_type_id = g_enum_register_static ("ScanMode", values); + g_once_init_leave (&scan_mode_type_id__volatile, scan_mode_type_id); + } + return scan_mode_type_id__volatile; +} + + +GType scan_type_get_type (void) { + static volatile gsize scan_type_type_id__volatile = 0; + if (g_once_init_enter (&scan_type_type_id__volatile)) { + static const GEnumValue values[] = {{SCAN_TYPE_SINGLE, "SCAN_TYPE_SINGLE", "single"}, {SCAN_TYPE_ADF_FRONT, "SCAN_TYPE_ADF_FRONT", "adf-front"}, {SCAN_TYPE_ADF_BACK, "SCAN_TYPE_ADF_BACK", "adf-back"}, {SCAN_TYPE_ADF_BOTH, "SCAN_TYPE_ADF_BOTH", "adf-both"}, {0, NULL, NULL}}; + GType scan_type_type_id; + scan_type_type_id = g_enum_register_static ("ScanType", values); + g_once_init_leave (&scan_type_type_id__volatile, scan_type_type_id); + } + return scan_type_type_id__volatile; +} + + +ScanOptions* scan_options_construct (GType object_type) { + ScanOptions* self = NULL; + self = (ScanOptions*) g_type_create_instance (object_type); + return self; +} + + +ScanOptions* scan_options_new (void) { + return scan_options_construct (TYPE_SCAN_OPTIONS); +} + + +static void value_scan_options_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_scan_options_free_value (GValue* value) { + if (value->data[0].v_pointer) { + scan_options_unref (value->data[0].v_pointer); + } +} + + +static void value_scan_options_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = scan_options_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_scan_options_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_scan_options_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + ScanOptions* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = scan_options_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_scan_options_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + ScanOptions** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = scan_options_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecScanOptions* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_OPTIONS), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_scan_options (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_OPTIONS), NULL); + return value->data[0].v_pointer; +} + + +void value_set_scan_options (GValue* value, gpointer v_object) { + ScanOptions* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_OPTIONS)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_OPTIONS)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + scan_options_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_options_unref (old); + } +} + + +void value_take_scan_options (GValue* value, gpointer v_object) { + ScanOptions* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_OPTIONS)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_OPTIONS)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_options_unref (old); + } +} + + +static void scan_options_class_init (ScanOptionsClass * klass) { + scan_options_parent_class = g_type_class_peek_parent (klass); + SCAN_OPTIONS_CLASS (klass)->finalize = scan_options_finalize; +} + + +static void scan_options_instance_init (ScanOptions * self) { + self->ref_count = 1; +} + + +static void scan_options_finalize (ScanOptions* obj) { + ScanOptions * self; + self = SCAN_OPTIONS (obj); +} + + +GType scan_options_get_type (void) { + static volatile gsize scan_options_type_id__volatile = 0; + if (g_once_init_enter (&scan_options_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_scan_options_init, value_scan_options_free_value, value_scan_options_copy_value, value_scan_options_peek_pointer, "p", value_scan_options_collect_value, "p", value_scan_options_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ScanOptionsClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_options_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanOptions), 0, (GInstanceInitFunc) scan_options_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType scan_options_type_id; + scan_options_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanOptions", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&scan_options_type_id__volatile, scan_options_type_id); + } + return scan_options_type_id__volatile; +} + + +gpointer scan_options_ref (gpointer instance) { + ScanOptions* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void scan_options_unref (gpointer instance) { + ScanOptions* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SCAN_OPTIONS_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +ScanJob* scan_job_construct (GType object_type) { + ScanJob* self = NULL; + self = (ScanJob*) g_type_create_instance (object_type); + return self; +} + + +ScanJob* scan_job_new (void) { + return scan_job_construct (TYPE_SCAN_JOB); +} + + +static void value_scan_job_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_scan_job_free_value (GValue* value) { + if (value->data[0].v_pointer) { + scan_job_unref (value->data[0].v_pointer); + } +} + + +static void value_scan_job_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = scan_job_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_scan_job_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_scan_job_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + ScanJob* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = scan_job_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_scan_job_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + ScanJob** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = scan_job_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_scan_job (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecScanJob* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_JOB), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_scan_job (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_JOB), NULL); + return value->data[0].v_pointer; +} + + +void value_set_scan_job (GValue* value, gpointer v_object) { + ScanJob* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_JOB)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_JOB)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + scan_job_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_job_unref (old); + } +} + + +void value_take_scan_job (GValue* value, gpointer v_object) { + ScanJob* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_JOB)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_JOB)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scan_job_unref (old); + } +} + + +static void scan_job_class_init (ScanJobClass * klass) { + scan_job_parent_class = g_type_class_peek_parent (klass); + SCAN_JOB_CLASS (klass)->finalize = scan_job_finalize; +} + + +static void scan_job_instance_init (ScanJob * self) { + self->ref_count = 1; +} + + +static void scan_job_finalize (ScanJob* obj) { + ScanJob * self; + self = SCAN_JOB (obj); + _g_free0 (self->device); +} + + +GType scan_job_get_type (void) { + static volatile gsize scan_job_type_id__volatile = 0; + if (g_once_init_enter (&scan_job_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_scan_job_init, value_scan_job_free_value, value_scan_job_copy_value, value_scan_job_peek_pointer, "p", value_scan_job_collect_value, "p", value_scan_job_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ScanJobClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_job_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanJob), 0, (GInstanceInitFunc) scan_job_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType scan_job_type_id; + scan_job_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanJob", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&scan_job_type_id__volatile, scan_job_type_id); + } + return scan_job_type_id__volatile; +} + + +gpointer scan_job_ref (gpointer instance) { + ScanJob* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void scan_job_unref (gpointer instance) { + ScanJob* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SCAN_JOB_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +Request* request_construct (GType object_type) { + Request* self = NULL; + self = (Request*) g_type_create_instance (object_type); + return self; +} + + +Request* request_new (void) { + return request_construct (TYPE_REQUEST); +} + + +static void value_request_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_request_free_value (GValue* value) { + if (value->data[0].v_pointer) { + request_unref (value->data[0].v_pointer); + } +} + + +static void value_request_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = request_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_request_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_request_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Request* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = request_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_request_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Request** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = request_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_request (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecRequest* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_REQUEST), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_request (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_REQUEST), NULL); + return value->data[0].v_pointer; +} + + +void value_set_request (GValue* value, gpointer v_object) { + Request* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_REQUEST)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_REQUEST)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + request_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + request_unref (old); + } +} + + +void value_take_request (GValue* value, gpointer v_object) { + Request* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_REQUEST)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_REQUEST)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + request_unref (old); + } +} + + +static void request_class_init (RequestClass * klass) { + request_parent_class = g_type_class_peek_parent (klass); + REQUEST_CLASS (klass)->finalize = request_finalize; +} + + +static void request_instance_init (Request * self) { + self->ref_count = 1; +} + + +static void request_finalize (Request* obj) { + Request * self; + self = REQUEST (obj); +} + + +GType request_get_type (void) { + static volatile gsize request_type_id__volatile = 0; + if (g_once_init_enter (&request_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_request_init, value_request_free_value, value_request_copy_value, value_request_peek_pointer, "p", value_request_collect_value, "p", value_request_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (RequestClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Request), 0, (GInstanceInitFunc) request_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType request_type_id; + request_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Request", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&request_type_id__volatile, request_type_id); + } + return request_type_id__volatile; +} + + +gpointer request_ref (gpointer instance) { + Request* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void request_unref (gpointer instance) { + Request* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + REQUEST_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +RequestRedetect* request_redetect_construct (GType object_type) { + RequestRedetect* self = NULL; + self = (RequestRedetect*) request_construct (object_type); + return self; +} + + +RequestRedetect* request_redetect_new (void) { + return request_redetect_construct (TYPE_REQUEST_REDETECT); +} + + +static void request_redetect_class_init (RequestRedetectClass * klass) { + request_redetect_parent_class = g_type_class_peek_parent (klass); +} + + +static void request_redetect_instance_init (RequestRedetect * self) { +} + + +GType request_redetect_get_type (void) { + static volatile gsize request_redetect_type_id__volatile = 0; + if (g_once_init_enter (&request_redetect_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (RequestRedetectClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_redetect_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestRedetect), 0, (GInstanceInitFunc) request_redetect_instance_init, NULL }; + GType request_redetect_type_id; + request_redetect_type_id = g_type_register_static (TYPE_REQUEST, "RequestRedetect", &g_define_type_info, 0); + g_once_init_leave (&request_redetect_type_id__volatile, request_redetect_type_id); + } + return request_redetect_type_id__volatile; +} + + +RequestCancel* request_cancel_construct (GType object_type) { + RequestCancel* self = NULL; + self = (RequestCancel*) request_construct (object_type); + return self; +} + + +RequestCancel* request_cancel_new (void) { + return request_cancel_construct (TYPE_REQUEST_CANCEL); +} + + +static void request_cancel_class_init (RequestCancelClass * klass) { + request_cancel_parent_class = g_type_class_peek_parent (klass); +} + + +static void request_cancel_instance_init (RequestCancel * self) { +} + + +GType request_cancel_get_type (void) { + static volatile gsize request_cancel_type_id__volatile = 0; + if (g_once_init_enter (&request_cancel_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (RequestCancelClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_cancel_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestCancel), 0, (GInstanceInitFunc) request_cancel_instance_init, NULL }; + GType request_cancel_type_id; + request_cancel_type_id = g_type_register_static (TYPE_REQUEST, "RequestCancel", &g_define_type_info, 0); + g_once_init_leave (&request_cancel_type_id__volatile, request_cancel_type_id); + } + return request_cancel_type_id__volatile; +} + + +RequestStartScan* request_start_scan_construct (GType object_type) { + RequestStartScan* self = NULL; + self = (RequestStartScan*) request_construct (object_type); + return self; +} + + +RequestStartScan* request_start_scan_new (void) { + return request_start_scan_construct (TYPE_REQUEST_START_SCAN); +} + + +static void request_start_scan_class_init (RequestStartScanClass * klass) { + request_start_scan_parent_class = g_type_class_peek_parent (klass); + REQUEST_CLASS (klass)->finalize = request_start_scan_finalize; +} + + +static void request_start_scan_instance_init (RequestStartScan * self) { +} + + +static void request_start_scan_finalize (Request* obj) { + RequestStartScan * self; + self = REQUEST_START_SCAN (obj); + _scan_job_unref0 (self->job); + REQUEST_CLASS (request_start_scan_parent_class)->finalize (obj); +} + + +GType request_start_scan_get_type (void) { + static volatile gsize request_start_scan_type_id__volatile = 0; + if (g_once_init_enter (&request_start_scan_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (RequestStartScanClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_start_scan_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestStartScan), 0, (GInstanceInitFunc) request_start_scan_instance_init, NULL }; + GType request_start_scan_type_id; + request_start_scan_type_id = g_type_register_static (TYPE_REQUEST, "RequestStartScan", &g_define_type_info, 0); + g_once_init_leave (&request_start_scan_type_id__volatile, request_start_scan_type_id); + } + return request_start_scan_type_id__volatile; +} + + +RequestQuit* request_quit_construct (GType object_type) { + RequestQuit* self = NULL; + self = (RequestQuit*) request_construct (object_type); + return self; +} + + +RequestQuit* request_quit_new (void) { + return request_quit_construct (TYPE_REQUEST_QUIT); +} + + +static void request_quit_class_init (RequestQuitClass * klass) { + request_quit_parent_class = g_type_class_peek_parent (klass); +} + + +static void request_quit_instance_init (RequestQuit * self) { +} + + +GType request_quit_get_type (void) { + static volatile gsize request_quit_type_id__volatile = 0; + if (g_once_init_enter (&request_quit_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (RequestQuitClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_quit_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestQuit), 0, (GInstanceInitFunc) request_quit_instance_init, NULL }; + GType request_quit_type_id; + request_quit_type_id = g_type_register_static (TYPE_REQUEST, "RequestQuit", &g_define_type_info, 0); + g_once_init_leave (&request_quit_type_id__volatile, request_quit_type_id); + } + return request_quit_type_id__volatile; +} + + +Credentials* credentials_construct (GType object_type) { + Credentials* self = NULL; + self = (Credentials*) g_type_create_instance (object_type); + return self; +} + + +Credentials* credentials_new (void) { + return credentials_construct (TYPE_CREDENTIALS); +} + + +static void value_credentials_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_credentials_free_value (GValue* value) { + if (value->data[0].v_pointer) { + credentials_unref (value->data[0].v_pointer); + } +} + + +static void value_credentials_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = credentials_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_credentials_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_credentials_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Credentials* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = credentials_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_credentials_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Credentials** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = credentials_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_credentials (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecCredentials* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_CREDENTIALS), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_credentials (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CREDENTIALS), NULL); + return value->data[0].v_pointer; +} + + +void value_set_credentials (GValue* value, gpointer v_object) { + Credentials* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CREDENTIALS)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_CREDENTIALS)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + credentials_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + credentials_unref (old); + } +} + + +void value_take_credentials (GValue* value, gpointer v_object) { + Credentials* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CREDENTIALS)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_CREDENTIALS)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + credentials_unref (old); + } +} + + +static void credentials_class_init (CredentialsClass * klass) { + credentials_parent_class = g_type_class_peek_parent (klass); + CREDENTIALS_CLASS (klass)->finalize = credentials_finalize; +} + + +static void credentials_instance_init (Credentials * self) { + self->ref_count = 1; +} + + +static void credentials_finalize (Credentials* obj) { + Credentials * self; + self = CREDENTIALS (obj); + _g_free0 (self->username); + _g_free0 (self->password); +} + + +GType credentials_get_type (void) { + static volatile gsize credentials_type_id__volatile = 0; + if (g_once_init_enter (&credentials_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_credentials_init, value_credentials_free_value, value_credentials_copy_value, value_credentials_peek_pointer, "p", value_credentials_collect_value, "p", value_credentials_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (CredentialsClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) credentials_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Credentials), 0, (GInstanceInitFunc) credentials_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType credentials_type_id; + credentials_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Credentials", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&credentials_type_id__volatile, credentials_type_id); + } + return credentials_type_id__volatile; +} + + +gpointer credentials_ref (gpointer instance) { + Credentials* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void credentials_unref (gpointer instance) { + Credentials* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + CREDENTIALS_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +GType scan_state_get_type (void) { + static volatile gsize scan_state_type_id__volatile = 0; + if (g_once_init_enter (&scan_state_type_id__volatile)) { + static const GEnumValue values[] = {{SCAN_STATE_IDLE, "SCAN_STATE_IDLE", "idle"}, {SCAN_STATE_REDETECT, "SCAN_STATE_REDETECT", "redetect"}, {SCAN_STATE_OPEN, "SCAN_STATE_OPEN", "open"}, {SCAN_STATE_GET_OPTION, "SCAN_STATE_GET_OPTION", "get-option"}, {SCAN_STATE_START, "SCAN_STATE_START", "start"}, {SCAN_STATE_GET_PARAMETERS, "SCAN_STATE_GET_PARAMETERS", "get-parameters"}, {SCAN_STATE_READ, "SCAN_STATE_READ", "read"}, {0, NULL, NULL}}; + GType scan_state_type_id; + scan_state_type_id = g_enum_register_static ("ScanState", values); + g_once_init_leave (&scan_state_type_id__volatile, scan_state_type_id); + } + return scan_state_type_id__volatile; +} + + +static void notify_real_run (Notify* self, Scanner* scanner) { + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); +} + + +void notify_run (Notify* self, Scanner* scanner) { + NOTIFY_GET_CLASS (self)->run (self, scanner); +} + + +Notify* notify_construct (GType object_type) { + Notify* self = NULL; + self = (Notify*) g_type_create_instance (object_type); + return self; +} + + +Notify* notify_new (void) { + return notify_construct (TYPE_NOTIFY); +} + + +static void value_notify_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_notify_free_value (GValue* value) { + if (value->data[0].v_pointer) { + notify_unref (value->data[0].v_pointer); + } +} + + +static void value_notify_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = notify_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_notify_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_notify_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Notify* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = notify_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_notify_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Notify** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = notify_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_notify (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecNotify* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_NOTIFY), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_notify (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_NOTIFY), NULL); + return value->data[0].v_pointer; +} + + +void value_set_notify (GValue* value, gpointer v_object) { + Notify* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_NOTIFY)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_NOTIFY)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + notify_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + notify_unref (old); + } +} + + +void value_take_notify (GValue* value, gpointer v_object) { + Notify* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_NOTIFY)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_NOTIFY)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + notify_unref (old); + } +} + + +static void notify_class_init (NotifyClass * klass) { + notify_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->finalize = notify_finalize; + NOTIFY_CLASS (klass)->run = notify_real_run; +} + + +static void notify_instance_init (Notify * self) { + self->ref_count = 1; +} + + +static void notify_finalize (Notify* obj) { + Notify * self; + self = NOTIFY (obj); +} + + +GType notify_get_type (void) { + static volatile gsize notify_type_id__volatile = 0; + if (g_once_init_enter (¬ify_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_notify_init, value_notify_free_value, value_notify_copy_value, value_notify_peek_pointer, "p", value_notify_collect_value, "p", value_notify_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (NotifyClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Notify), 0, (GInstanceInitFunc) notify_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType notify_type_id; + notify_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Notify", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (¬ify_type_id__volatile, notify_type_id); + } + return notify_type_id__volatile; +} + + +gpointer notify_ref (gpointer instance) { + Notify* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void notify_unref (gpointer instance) { + Notify* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + NOTIFY_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +static void notify_scanning_changed_real_run (Notify* base, Scanner* scanner) { + NotifyScanningChanged * self; + self = (NotifyScanningChanged*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "scanning-changed"); +} + + +NotifyScanningChanged* notify_scanning_changed_construct (GType object_type) { + NotifyScanningChanged* self = NULL; + self = (NotifyScanningChanged*) notify_construct (object_type); + return self; +} + + +NotifyScanningChanged* notify_scanning_changed_new (void) { + return notify_scanning_changed_construct (TYPE_NOTIFY_SCANNING_CHANGED); +} + + +static void notify_scanning_changed_class_init (NotifyScanningChangedClass * klass) { + notify_scanning_changed_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->run = notify_scanning_changed_real_run; +} + + +static void notify_scanning_changed_instance_init (NotifyScanningChanged * self) { +} + + +GType notify_scanning_changed_get_type (void) { + static volatile gsize notify_scanning_changed_type_id__volatile = 0; + if (g_once_init_enter (¬ify_scanning_changed_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyScanningChangedClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_scanning_changed_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyScanningChanged), 0, (GInstanceInitFunc) notify_scanning_changed_instance_init, NULL }; + GType notify_scanning_changed_type_id; + notify_scanning_changed_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyScanningChanged", &g_define_type_info, 0); + g_once_init_leave (¬ify_scanning_changed_type_id__volatile, notify_scanning_changed_type_id); + } + return notify_scanning_changed_type_id__volatile; +} + + +static void _scan_device_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (scan_device_unref (var), NULL)); +} + + +static void _g_list_free__scan_device_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _scan_device_unref0_, NULL); + g_list_free (self); +} + + +NotifyUpdateDevices* notify_update_devices_construct (GType object_type, GList* devices) { + NotifyUpdateDevices* self = NULL; + GList* _tmp0_; + self = (NotifyUpdateDevices*) notify_construct (object_type); + _tmp0_ = devices; + devices = NULL; + __g_list_free__scan_device_unref0_0 (self->priv->devices); + self->priv->devices = _tmp0_; + __g_list_free__scan_device_unref0_0 (devices); + return self; +} + + +NotifyUpdateDevices* notify_update_devices_new (GList* devices) { + return notify_update_devices_construct (TYPE_NOTIFY_UPDATE_DEVICES, devices); +} + + +static void notify_update_devices_real_run (Notify* base, Scanner* scanner) { + NotifyUpdateDevices * self; + self = (NotifyUpdateDevices*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "update-devices", self->priv->devices); +} + + +static void notify_update_devices_class_init (NotifyUpdateDevicesClass * klass) { + notify_update_devices_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->finalize = notify_update_devices_finalize; + g_type_class_add_private (klass, sizeof (NotifyUpdateDevicesPrivate)); + NOTIFY_CLASS (klass)->run = notify_update_devices_real_run; +} + + +static void notify_update_devices_instance_init (NotifyUpdateDevices * self) { + self->priv = NOTIFY_UPDATE_DEVICES_GET_PRIVATE (self); +} + + +static void notify_update_devices_finalize (Notify* obj) { + NotifyUpdateDevices * self; + self = NOTIFY_UPDATE_DEVICES (obj); + __g_list_free__scan_device_unref0_0 (self->priv->devices); + NOTIFY_CLASS (notify_update_devices_parent_class)->finalize (obj); +} + + +GType notify_update_devices_get_type (void) { + static volatile gsize notify_update_devices_type_id__volatile = 0; + if (g_once_init_enter (¬ify_update_devices_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyUpdateDevicesClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_update_devices_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyUpdateDevices), 0, (GInstanceInitFunc) notify_update_devices_instance_init, NULL }; + GType notify_update_devices_type_id; + notify_update_devices_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyUpdateDevices", &g_define_type_info, 0); + g_once_init_leave (¬ify_update_devices_type_id__volatile, notify_update_devices_type_id); + } + return notify_update_devices_type_id__volatile; +} + + +NotifyRequestAuthorization* notify_request_authorization_construct (GType object_type, const gchar* resource) { + NotifyRequestAuthorization* self = NULL; + gchar* _tmp0_; + g_return_val_if_fail (resource != NULL, NULL); + self = (NotifyRequestAuthorization*) notify_construct (object_type); + _tmp0_ = g_strdup (resource); + _g_free0 (self->priv->resource); + self->priv->resource = _tmp0_; + return self; +} + + +NotifyRequestAuthorization* notify_request_authorization_new (const gchar* resource) { + return notify_request_authorization_construct (TYPE_NOTIFY_REQUEST_AUTHORIZATION, resource); +} + + +static void notify_request_authorization_real_run (Notify* base, Scanner* scanner) { + NotifyRequestAuthorization * self; + self = (NotifyRequestAuthorization*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "request-authorization", self->priv->resource); +} + + +static void notify_request_authorization_class_init (NotifyRequestAuthorizationClass * klass) { + notify_request_authorization_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->finalize = notify_request_authorization_finalize; + g_type_class_add_private (klass, sizeof (NotifyRequestAuthorizationPrivate)); + NOTIFY_CLASS (klass)->run = notify_request_authorization_real_run; +} + + +static void notify_request_authorization_instance_init (NotifyRequestAuthorization * self) { + self->priv = NOTIFY_REQUEST_AUTHORIZATION_GET_PRIVATE (self); +} + + +static void notify_request_authorization_finalize (Notify* obj) { + NotifyRequestAuthorization * self; + self = NOTIFY_REQUEST_AUTHORIZATION (obj); + _g_free0 (self->priv->resource); + NOTIFY_CLASS (notify_request_authorization_parent_class)->finalize (obj); +} + + +GType notify_request_authorization_get_type (void) { + static volatile gsize notify_request_authorization_type_id__volatile = 0; + if (g_once_init_enter (¬ify_request_authorization_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyRequestAuthorizationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_request_authorization_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyRequestAuthorization), 0, (GInstanceInitFunc) notify_request_authorization_instance_init, NULL }; + GType notify_request_authorization_type_id; + notify_request_authorization_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyRequestAuthorization", &g_define_type_info, 0); + g_once_init_leave (¬ify_request_authorization_type_id__volatile, notify_request_authorization_type_id); + } + return notify_request_authorization_type_id__volatile; +} + + +NotifyScanFailed* notify_scan_failed_construct (GType object_type, gint error_code, const gchar* error_string) { + NotifyScanFailed* self = NULL; + gchar* _tmp0_; + g_return_val_if_fail (error_string != NULL, NULL); + self = (NotifyScanFailed*) notify_construct (object_type); + self->priv->error_code = error_code; + _tmp0_ = g_strdup (error_string); + _g_free0 (self->priv->error_string); + self->priv->error_string = _tmp0_; + return self; +} + + +NotifyScanFailed* notify_scan_failed_new (gint error_code, const gchar* error_string) { + return notify_scan_failed_construct (TYPE_NOTIFY_SCAN_FAILED, error_code, error_string); +} + + +static void notify_scan_failed_real_run (Notify* base, Scanner* scanner) { + NotifyScanFailed * self; + self = (NotifyScanFailed*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "scan-failed", self->priv->error_code, self->priv->error_string); +} + + +static void notify_scan_failed_class_init (NotifyScanFailedClass * klass) { + notify_scan_failed_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->finalize = notify_scan_failed_finalize; + g_type_class_add_private (klass, sizeof (NotifyScanFailedPrivate)); + NOTIFY_CLASS (klass)->run = notify_scan_failed_real_run; +} + + +static void notify_scan_failed_instance_init (NotifyScanFailed * self) { + self->priv = NOTIFY_SCAN_FAILED_GET_PRIVATE (self); +} + + +static void notify_scan_failed_finalize (Notify* obj) { + NotifyScanFailed * self; + self = NOTIFY_SCAN_FAILED (obj); + _g_free0 (self->priv->error_string); + NOTIFY_CLASS (notify_scan_failed_parent_class)->finalize (obj); +} + + +GType notify_scan_failed_get_type (void) { + static volatile gsize notify_scan_failed_type_id__volatile = 0; + if (g_once_init_enter (¬ify_scan_failed_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyScanFailedClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_scan_failed_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyScanFailed), 0, (GInstanceInitFunc) notify_scan_failed_instance_init, NULL }; + GType notify_scan_failed_type_id; + notify_scan_failed_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyScanFailed", &g_define_type_info, 0); + g_once_init_leave (¬ify_scan_failed_type_id__volatile, notify_scan_failed_type_id); + } + return notify_scan_failed_type_id__volatile; +} + + +static void notify_document_done_real_run (Notify* base, Scanner* scanner) { + NotifyDocumentDone * self; + self = (NotifyDocumentDone*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "document-done"); +} + + +NotifyDocumentDone* notify_document_done_construct (GType object_type) { + NotifyDocumentDone* self = NULL; + self = (NotifyDocumentDone*) notify_construct (object_type); + return self; +} + + +NotifyDocumentDone* notify_document_done_new (void) { + return notify_document_done_construct (TYPE_NOTIFY_DOCUMENT_DONE); +} + + +static void notify_document_done_class_init (NotifyDocumentDoneClass * klass) { + notify_document_done_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->run = notify_document_done_real_run; +} + + +static void notify_document_done_instance_init (NotifyDocumentDone * self) { +} + + +GType notify_document_done_get_type (void) { + static volatile gsize notify_document_done_type_id__volatile = 0; + if (g_once_init_enter (¬ify_document_done_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyDocumentDoneClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_document_done_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyDocumentDone), 0, (GInstanceInitFunc) notify_document_done_instance_init, NULL }; + GType notify_document_done_type_id; + notify_document_done_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyDocumentDone", &g_define_type_info, 0); + g_once_init_leave (¬ify_document_done_type_id__volatile, notify_document_done_type_id); + } + return notify_document_done_type_id__volatile; +} + + +static void notify_expect_page_real_run (Notify* base, Scanner* scanner) { + NotifyExpectPage * self; + self = (NotifyExpectPage*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "expect-page"); +} + + +NotifyExpectPage* notify_expect_page_construct (GType object_type) { + NotifyExpectPage* self = NULL; + self = (NotifyExpectPage*) notify_construct (object_type); + return self; +} + + +NotifyExpectPage* notify_expect_page_new (void) { + return notify_expect_page_construct (TYPE_NOTIFY_EXPECT_PAGE); +} + + +static void notify_expect_page_class_init (NotifyExpectPageClass * klass) { + notify_expect_page_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->run = notify_expect_page_real_run; +} + + +static void notify_expect_page_instance_init (NotifyExpectPage * self) { +} + + +GType notify_expect_page_get_type (void) { + static volatile gsize notify_expect_page_type_id__volatile = 0; + if (g_once_init_enter (¬ify_expect_page_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyExpectPageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_expect_page_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyExpectPage), 0, (GInstanceInitFunc) notify_expect_page_instance_init, NULL }; + GType notify_expect_page_type_id; + notify_expect_page_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyExpectPage", &g_define_type_info, 0); + g_once_init_leave (¬ify_expect_page_type_id__volatile, notify_expect_page_type_id); + } + return notify_expect_page_type_id__volatile; +} + + +static gpointer _scan_page_info_ref0 (gpointer self) { + return self ? scan_page_info_ref (self) : NULL; +} + + +NotifyGotPageInfo* notify_got_page_info_construct (GType object_type, ScanPageInfo* info) { + NotifyGotPageInfo* self = NULL; + ScanPageInfo* _tmp0_; + g_return_val_if_fail (info != NULL, NULL); + self = (NotifyGotPageInfo*) notify_construct (object_type); + _tmp0_ = _scan_page_info_ref0 (info); + _scan_page_info_unref0 (self->priv->info); + self->priv->info = _tmp0_; + return self; +} + + +NotifyGotPageInfo* notify_got_page_info_new (ScanPageInfo* info) { + return notify_got_page_info_construct (TYPE_NOTIFY_GOT_PAGE_INFO, info); +} + + +static void notify_got_page_info_real_run (Notify* base, Scanner* scanner) { + NotifyGotPageInfo * self; + self = (NotifyGotPageInfo*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "got-page-info", self->priv->info); +} + + +static void notify_got_page_info_class_init (NotifyGotPageInfoClass * klass) { + notify_got_page_info_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->finalize = notify_got_page_info_finalize; + g_type_class_add_private (klass, sizeof (NotifyGotPageInfoPrivate)); + NOTIFY_CLASS (klass)->run = notify_got_page_info_real_run; +} + + +static void notify_got_page_info_instance_init (NotifyGotPageInfo * self) { + self->priv = NOTIFY_GOT_PAGE_INFO_GET_PRIVATE (self); +} + + +static void notify_got_page_info_finalize (Notify* obj) { + NotifyGotPageInfo * self; + self = NOTIFY_GOT_PAGE_INFO (obj); + _scan_page_info_unref0 (self->priv->info); + NOTIFY_CLASS (notify_got_page_info_parent_class)->finalize (obj); +} + + +GType notify_got_page_info_get_type (void) { + static volatile gsize notify_got_page_info_type_id__volatile = 0; + if (g_once_init_enter (¬ify_got_page_info_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyGotPageInfoClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_got_page_info_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyGotPageInfo), 0, (GInstanceInitFunc) notify_got_page_info_instance_init, NULL }; + GType notify_got_page_info_type_id; + notify_got_page_info_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyGotPageInfo", &g_define_type_info, 0); + g_once_init_leave (¬ify_got_page_info_type_id__volatile, notify_got_page_info_type_id); + } + return notify_got_page_info_type_id__volatile; +} + + +static void notify_page_done_real_run (Notify* base, Scanner* scanner) { + NotifyPageDone * self; + self = (NotifyPageDone*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "page-done"); +} + + +NotifyPageDone* notify_page_done_construct (GType object_type) { + NotifyPageDone* self = NULL; + self = (NotifyPageDone*) notify_construct (object_type); + return self; +} + + +NotifyPageDone* notify_page_done_new (void) { + return notify_page_done_construct (TYPE_NOTIFY_PAGE_DONE); +} + + +static void notify_page_done_class_init (NotifyPageDoneClass * klass) { + notify_page_done_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->run = notify_page_done_real_run; +} + + +static void notify_page_done_instance_init (NotifyPageDone * self) { +} + + +GType notify_page_done_get_type (void) { + static volatile gsize notify_page_done_type_id__volatile = 0; + if (g_once_init_enter (¬ify_page_done_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyPageDoneClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_page_done_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyPageDone), 0, (GInstanceInitFunc) notify_page_done_instance_init, NULL }; + GType notify_page_done_type_id; + notify_page_done_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyPageDone", &g_define_type_info, 0); + g_once_init_leave (¬ify_page_done_type_id__volatile, notify_page_done_type_id); + } + return notify_page_done_type_id__volatile; +} + + +static gpointer _scan_line_ref0 (gpointer self) { + return self ? scan_line_ref (self) : NULL; +} + + +NotifyGotLine* notify_got_line_construct (GType object_type, ScanLine* line) { + NotifyGotLine* self = NULL; + ScanLine* _tmp0_; + g_return_val_if_fail (line != NULL, NULL); + self = (NotifyGotLine*) notify_construct (object_type); + _tmp0_ = _scan_line_ref0 (line); + _scan_line_unref0 (self->priv->line); + self->priv->line = _tmp0_; + return self; +} + + +NotifyGotLine* notify_got_line_new (ScanLine* line) { + return notify_got_line_construct (TYPE_NOTIFY_GOT_LINE, line); +} + + +static void notify_got_line_real_run (Notify* base, Scanner* scanner) { + NotifyGotLine * self; + self = (NotifyGotLine*) base; + g_return_if_fail (scanner != NULL); + g_signal_emit_by_name (scanner, "got-line", self->priv->line); +} + + +static void notify_got_line_class_init (NotifyGotLineClass * klass) { + notify_got_line_parent_class = g_type_class_peek_parent (klass); + NOTIFY_CLASS (klass)->finalize = notify_got_line_finalize; + g_type_class_add_private (klass, sizeof (NotifyGotLinePrivate)); + NOTIFY_CLASS (klass)->run = notify_got_line_real_run; +} + + +static void notify_got_line_instance_init (NotifyGotLine * self) { + self->priv = NOTIFY_GOT_LINE_GET_PRIVATE (self); +} + + +static void notify_got_line_finalize (Notify* obj) { + NotifyGotLine * self; + self = NOTIFY_GOT_LINE (obj); + _scan_line_unref0 (self->priv->line); + NOTIFY_CLASS (notify_got_line_parent_class)->finalize (obj); +} + + +GType notify_got_line_get_type (void) { + static volatile gsize notify_got_line_type_id__volatile = 0; + if (g_once_init_enter (¬ify_got_line_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (NotifyGotLineClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_got_line_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyGotLine), 0, (GInstanceInitFunc) notify_got_line_instance_init, NULL }; + GType notify_got_line_type_id; + notify_got_line_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyGotLine", &g_define_type_info, 0); + g_once_init_leave (¬ify_got_line_type_id__volatile, notify_got_line_type_id); + } + return notify_got_line_type_id__volatile; +} + + +static void _scan_job_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (scan_job_unref (var), NULL)); +} + + +static void _g_list_free__scan_job_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _scan_job_unref0_, NULL); + g_list_free (self); +} + + +static Scanner* scanner_construct (GType object_type) { + Scanner* self = NULL; + GAsyncQueue* _tmp0_ = NULL; + GAsyncQueue* _tmp1_ = NULL; + GAsyncQueue* _tmp2_ = NULL; + self = (Scanner*) g_type_create_instance (object_type); + _tmp0_ = g_async_queue_new (); + _g_async_queue_unref0 (self->priv->request_queue); + self->priv->request_queue = _tmp0_; + _tmp1_ = g_async_queue_new (); + _g_async_queue_unref0 (self->priv->notify_queue); + self->priv->notify_queue = _tmp1_; + _tmp2_ = g_async_queue_new (); + _g_async_queue_unref0 (self->priv->authorize_queue); + self->priv->authorize_queue = _tmp2_; + return self; +} + + +static Scanner* scanner_new (void) { + return scanner_construct (TYPE_SCANNER); +} + + +static gpointer _scanner_ref0 (gpointer self) { + return self ? scanner_ref (self) : NULL; +} + + +Scanner* scanner_get_instance (void) { + Scanner* result = NULL; + Scanner* _tmp1_; + if (scanner_scanner_object == NULL) { + Scanner* _tmp0_ = NULL; + _tmp0_ = scanner_new (); + _scanner_unref0 (scanner_scanner_object); + scanner_scanner_object = _tmp0_; + } + _tmp1_ = _scanner_ref0 (scanner_scanner_object); + result = _tmp1_; + return result; +} + + +static gboolean scanner_notify_idle_cb (Scanner* self) { + gboolean result = FALSE; + gpointer _tmp0_ = NULL; + Notify* notification; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = g_async_queue_pop (self->priv->notify_queue); + notification = (Notify*) _tmp0_; + notify_run (notification, self); + result = FALSE; + _notify_unref0 (notification); + return result; +} + + +static gpointer _notify_ref0 (gpointer self) { + return self ? notify_ref (self) : NULL; +} + + +static gboolean _scanner_notify_idle_cb_gsource_func (gpointer self) { + gboolean result; + result = scanner_notify_idle_cb (self); + return result; +} + + +static void scanner_notify (Scanner* self, Notify* notification) { + Notify* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (notification != NULL); + _tmp0_ = _notify_ref0 (notification); + g_async_queue_push (self->priv->notify_queue, _tmp0_); + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, _scanner_notify_idle_cb_gsource_func, scanner_ref (self), scanner_unref); +} + + +static void scanner_set_scanning (Scanner* self, gboolean is_scanning) { + gboolean _tmp0_ = FALSE; + gboolean _tmp1_ = FALSE; + g_return_if_fail (self != NULL); + if (self->priv->scanning) { + _tmp1_ = !is_scanning; + } else { + _tmp1_ = FALSE; + } + if (_tmp1_) { + _tmp0_ = TRUE; + } else { + gboolean _tmp2_ = FALSE; + if (!self->priv->scanning) { + _tmp2_ = is_scanning; + } else { + _tmp2_ = FALSE; + } + _tmp0_ = _tmp2_; + } + if (_tmp0_) { + NotifyScanningChanged* _tmp3_ = NULL; + NotifyScanningChanged* _tmp4_; + self->priv->scanning = is_scanning; + g_signal_emit_by_name (self, "scanning-changed"); + _tmp3_ = notify_scanning_changed_new (); + _tmp4_ = _tmp3_; + scanner_notify (self, (Notify*) _tmp4_); + _notify_unref0 (_tmp4_); + } +} + + +static gboolean string_contains (const gchar* self, const gchar* needle) { + gboolean result = FALSE; + gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (needle != NULL, FALSE); + _tmp0_ = strstr ((gchar*) self, (gchar*) needle); + result = _tmp0_ != NULL; + return result; +} + + +static gint scanner_get_device_weight (const gchar* device) { + gint result = 0; + gboolean _tmp0_; + gboolean _tmp1_; + g_return_val_if_fail (device != NULL, 0); + _tmp0_ = g_str_has_prefix (device, "vfl:"); + if (_tmp0_) { + result = 2; + return result; + } + _tmp1_ = string_contains (device, "usb"); + if (_tmp1_) { + result = 0; + return result; + } + result = 1; + return result; +} + + +static gint scanner_compare_devices (ScanDevice* device1, ScanDevice* device2) { + gint result = 0; + gint _tmp0_; + gint weight1; + gint _tmp1_; + gint weight2; + gint _tmp2_; + g_return_val_if_fail (device1 != NULL, 0); + g_return_val_if_fail (device2 != NULL, 0); + _tmp0_ = scanner_get_device_weight (device1->name); + weight1 = _tmp0_; + _tmp1_ = scanner_get_device_weight (device2->name); + weight2 = _tmp1_; + if (weight1 != weight2) { + result = weight1 - weight2; + return result; + } + _tmp2_ = g_strcmp0 (device1->label, device2->label); + result = _tmp2_; + return result; +} + + +static gchar* sane_status_to_string (SANE_Status status) { + gchar* result = NULL; + switch (status) { + case SANE_STATUS_GOOD: + { + gchar* _tmp0_; + _tmp0_ = g_strdup ("SANE_STATUS_GOOD"); + result = _tmp0_; + return result; + } + case SANE_STATUS_UNSUPPORTED: + { + gchar* _tmp1_; + _tmp1_ = g_strdup ("SANE_STATUS_UNSUPPORTED"); + result = _tmp1_; + return result; + } + case SANE_STATUS_CANCELLED: + { + gchar* _tmp2_; + _tmp2_ = g_strdup ("SANE_STATUS_CANCELLED"); + result = _tmp2_; + return result; + } + case SANE_STATUS_DEVICE_BUSY: + { + gchar* _tmp3_; + _tmp3_ = g_strdup ("SANE_STATUS_DEVICE_BUSY"); + result = _tmp3_; + return result; + } + case SANE_STATUS_INVAL: + { + gchar* _tmp4_; + _tmp4_ = g_strdup ("SANE_STATUS_INVAL"); + result = _tmp4_; + return result; + } + case SANE_STATUS_EOF: + { + gchar* _tmp5_; + _tmp5_ = g_strdup ("SANE_STATUS_EOF"); + result = _tmp5_; + return result; + } + case SANE_STATUS_JAMMED: + { + gchar* _tmp6_; + _tmp6_ = g_strdup ("SANE_STATUS_JAMMED"); + result = _tmp6_; + return result; + } + case SANE_STATUS_NO_DOCS: + { + gchar* _tmp7_; + _tmp7_ = g_strdup ("SANE_STATUS_NO_DOCS"); + result = _tmp7_; + return result; + } + case SANE_STATUS_COVER_OPEN: + { + gchar* _tmp8_; + _tmp8_ = g_strdup ("SANE_STATUS_COVER_OPEN"); + result = _tmp8_; + return result; + } + case SANE_STATUS_IO_ERROR: + { + gchar* _tmp9_; + _tmp9_ = g_strdup ("SANE_STATUS_IO_ERROR"); + result = _tmp9_; + return result; + } + case SANE_STATUS_NO_MEM: + { + gchar* _tmp10_; + _tmp10_ = g_strdup ("SANE_STATUS_NO_MEM"); + result = _tmp10_; + return result; + } + case SANE_STATUS_ACCESS_DENIED: + { + gchar* _tmp11_; + _tmp11_ = g_strdup ("SANE_STATUS_ACCESS_DENIED"); + result = _tmp11_; + return result; + } + default: + { + gchar* _tmp12_ = NULL; + _tmp12_ = g_strdup_printf ("SANE_STATUS(%d)", (gint) status); + result = _tmp12_; + return result; + } + } +} + + +static gchar* string_replace (const gchar* self, const gchar* old, const gchar* replacement) { + gchar* result = NULL; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (old != NULL, NULL); + g_return_val_if_fail (replacement != NULL, NULL); + { + gchar* _tmp0_ = NULL; + gchar* _tmp1_; + GRegex* _tmp2_ = NULL; + GRegex* _tmp3_; + GRegex* regex; + gchar* _tmp4_ = NULL; + gchar* _tmp5_; + _tmp0_ = g_regex_escape_string (old, -1); + _tmp1_ = _tmp0_; + _tmp2_ = g_regex_new (_tmp1_, 0, 0, &_inner_error_); + _tmp3_ = _tmp2_; + _g_free0 (_tmp1_); + regex = _tmp3_; + if (_inner_error_ != NULL) { + if (_inner_error_->domain == G_REGEX_ERROR) { + goto __catch8_g_regex_error; + } + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + _tmp4_ = g_regex_replace_literal (regex, self, (gssize) (-1), 0, replacement, 0, &_inner_error_); + _tmp5_ = _tmp4_; + if (_inner_error_ != NULL) { + _g_regex_unref0 (regex); + if (_inner_error_->domain == G_REGEX_ERROR) { + goto __catch8_g_regex_error; + } + _g_regex_unref0 (regex); + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + result = _tmp5_; + _g_regex_unref0 (regex); + return result; + } + goto __finally8; + __catch8_g_regex_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_assert_not_reached (); + _g_error_free0 (e); + } + __finally8: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } +} + + +static gpointer _scan_device_ref0 (gpointer self) { + return self ? scan_device_ref (self) : NULL; +} + + +static gint _scanner_compare_devices_gcompare_func (gconstpointer a, gconstpointer b) { + gint result; + result = scanner_compare_devices (a, b); + return result; +} + + +static void scanner_do_redetect (Scanner* self) { + SANE_Device** device_list; + gint device_list_length1; + gint _device_list_size_; + SANE_Device** _tmp0_ = NULL; + SANE_Status _tmp1_; + SANE_Status status; + gchar* _tmp2_ = NULL; + gchar* _tmp3_; + GList* devices; + GList* _tmp17_; + NotifyUpdateDevices* _tmp18_ = NULL; + NotifyUpdateDevices* _tmp19_; + g_return_if_fail (self != NULL); + device_list = NULL; + device_list_length1 = 0; + _device_list_size_ = device_list_length1; + _tmp1_ = sane_get_devices (&_tmp0_, FALSE); + device_list = _tmp0_; + device_list_length1 = -1; + _device_list_size_ = device_list_length1; + status = _tmp1_; + _tmp2_ = sane_status_to_string (status); + _tmp3_ = _tmp2_; + g_debug ("scanner.vala:318: sane_get_devices () -> %s", _tmp3_); + _g_free0 (_tmp3_); + if (status != SANE_STATUS_GOOD) { + const gchar* _tmp4_ = NULL; + _tmp4_ = sane_strstatus (status); + g_warning ("scanner.vala:321: Unable to get SANE devices: %s", _tmp4_); + self->priv->need_redetect = FALSE; + self->priv->state = SCAN_STATE_IDLE; + return; + } + devices = NULL; + { + gint i; + i = 0; + { + gboolean _tmp5_; + _tmp5_ = TRUE; + while (TRUE) { + ScanDevice* _tmp6_ = NULL; + ScanDevice* scan_device; + gchar* _tmp7_; + gchar* _tmp8_; + gchar* vendor; + gchar* _tmp10_ = NULL; + gchar* _tmp11_ = NULL; + gchar* _tmp12_; + ScanDevice* _tmp13_; + if (!_tmp5_) { + i++; + } + _tmp5_ = FALSE; + if (!(device_list[i] != NULL)) { + break; + } + g_debug ("scanner.vala:330: Device: name=\"%s\" vendor=\"%s\" model=\"%s\" type=" \ +"\"%s\"", device_list[i]->name, device_list[i]->vendor, device_list[i]->model, device_list[i]->type); + _tmp6_ = scan_device_new (); + scan_device = _tmp6_; + _tmp7_ = g_strdup (device_list[i]->name); + _g_free0 (scan_device->name); + scan_device->name = _tmp7_; + _tmp8_ = g_strdup (device_list[i]->vendor); + vendor = _tmp8_; + if (g_strcmp0 (vendor, "Hewlett-Packard") == 0) { + gchar* _tmp9_; + _tmp9_ = g_strdup ("HP"); + _g_free0 (vendor); + vendor = _tmp9_; + } + _tmp10_ = g_strdup_printf ("%s %s", vendor, device_list[i]->model); + _g_free0 (scan_device->label); + scan_device->label = _tmp10_; + _tmp11_ = string_replace (scan_device->label, "_", " "); + _tmp12_ = _tmp11_; + _g_free0 (_tmp12_); + _tmp13_ = _scan_device_ref0 (scan_device); + devices = g_list_append (devices, _tmp13_); + _g_free0 (vendor); + _scan_device_unref0 (scan_device); + } + } + } + devices = g_list_sort (devices, _scanner_compare_devices_gcompare_func); + self->priv->need_redetect = FALSE; + self->priv->state = SCAN_STATE_IDLE; + if (devices != NULL) { + gconstpointer _tmp14_ = NULL; + ScanDevice* _tmp15_; + ScanDevice* device; + gchar* _tmp16_; + _tmp14_ = g_list_nth_data (devices, (guint) 0); + _tmp15_ = _scan_device_ref0 ((ScanDevice*) _tmp14_); + device = _tmp15_; + _tmp16_ = g_strdup (device->name); + _g_free0 (self->priv->default_device); + self->priv->default_device = _tmp16_; + _scan_device_unref0 (device); + } else { + _g_free0 (self->priv->default_device); + self->priv->default_device = NULL; + } + _tmp17_ = devices; + devices = NULL; + _tmp18_ = notify_update_devices_new (_tmp17_); + _tmp19_ = _tmp18_; + scanner_notify (self, (Notify*) _tmp19_); + _notify_unref0 (_tmp19_); + __g_list_free__scan_device_unref0_0 (devices); +} + + +static gboolean scanner_set_default_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index) { + gboolean result = FALSE; + SANE_Status _tmp0_; + SANE_Status status; + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (option != NULL, FALSE); + if (((gint) (option->cap & SANE_CAP_AUTOMATIC)) == 0) { + result = FALSE; + return result; + } + _tmp0_ = sane_control_option (handle, option_index, SANE_ACTION_SET_AUTO, NULL, NULL); + status = _tmp0_; + _tmp1_ = sane_status_to_string (status); + _tmp2_ = _tmp1_; + g_debug ("scanner.vala:372: sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s", (gint) option_index, _tmp2_); + _g_free0 (_tmp2_); + if (status != SANE_STATUS_GOOD) { + const gchar* _tmp3_ = NULL; + _tmp3_ = sane_strstatus (status); + g_warning ("scanner.vala:374: Error setting default option %s: %s", option->name, _tmp3_); + } + result = status == SANE_STATUS_GOOD; + return result; +} + + +static void scanner_set_bool_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gboolean value, gboolean* _result_) { + gboolean _result = FALSE; + SANE_Bool v; + SANE_Status _tmp0_; + SANE_Status status; + const gchar* _tmp1_ = NULL; + const gchar* _tmp2_ = NULL; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + g_return_if_fail (self != NULL); + g_return_if_fail (option != NULL); + g_return_if_fail (option->type == SANE_TYPE_BOOL); + v = (SANE_Bool) value; + _tmp0_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, &v, NULL); + status = _tmp0_; + _result = (gboolean) v; + if (value) { + _tmp1_ = "SANE_TRUE"; + } else { + _tmp1_ = "SANE_FALSE"; + } + if (_result) { + _tmp2_ = "SANE_TRUE"; + } else { + _tmp2_ = "SANE_FALSE"; + } + _tmp3_ = sane_status_to_string (status); + _tmp4_ = _tmp3_; + g_debug ("scanner.vala:386: sane_control_option (%d, SANE_ACTION_SET_VALUE, %s) " \ +"-> (%s, %s)", (gint) option_index, _tmp1_, _tmp4_, _tmp2_); + _g_free0 (_tmp4_); + if (_result_) { + *_result_ = _result; + } +} + + +static void scanner_set_int_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gint value, gint* _result_) { + gint _result = 0; + SANE_Int v; + SANE_Status _tmp2_; + SANE_Status status; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + g_return_if_fail (self != NULL); + g_return_if_fail (option != NULL); + g_return_if_fail (option->type == SANE_TYPE_INT); + v = (SANE_Int) value; + if (option->constraint_type == SANE_CONSTRAINT_RANGE) { + if (((gint) option->constraint.range->quant) != 0) { + v = v * option->constraint.range->quant; + } + if (v < ((SANE_Int) option->constraint.range->min)) { + v = (SANE_Int) option->constraint.range->min; + } + if (v > ((SANE_Int) option->constraint.range->max)) { + v = (SANE_Int) option->constraint.range->max; + } + } else { + if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) { + gint distance; + gint nearest; + distance = G_MAXINT; + nearest = 0; + { + gint i; + i = 0; + { + gboolean _tmp0_; + _tmp0_ = TRUE; + while (TRUE) { + gint x; + gint _tmp1_; + gint d; + if (!_tmp0_) { + i++; + } + _tmp0_ = FALSE; + if (!(i < ((gint) option->constraint.word_list[0]))) { + break; + } + x = (gint) option->constraint.word_list[i + 1]; + _tmp1_ = abs (x - v); + d = _tmp1_; + if (d < distance) { + distance = d; + nearest = x; + } + } + } + } + v = (SANE_Int) nearest; + } + } + _tmp2_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, &v, NULL); + status = _tmp2_; + _tmp3_ = sane_status_to_string (status); + _tmp4_ = _tmp3_; + g_debug ("scanner.vala:422: sane_control_option (%d, SANE_ACTION_SET_VALUE, %d) " \ +"-> (%s, %d)", (gint) option_index, value, _tmp4_, (gint) v); + _g_free0 (_tmp4_); + _result = (gint) v; + if (_result_) { + *_result_ = _result; + } +} + + +static void scanner_set_fixed_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gdouble value, gdouble* _result_) { + gdouble _result = 0.0; + gdouble v; + SANE_Fixed v_fixed; + SANE_Fixed _tmp6_; + SANE_Status _tmp7_; + SANE_Status status; + gchar* _tmp8_ = NULL; + gchar* _tmp9_; + gdouble _tmp10_; + gdouble _tmp11_; + g_return_if_fail (self != NULL); + g_return_if_fail (option != NULL); + v = value; + g_return_if_fail (option->type == SANE_TYPE_FIXED); + if (option->constraint_type == SANE_CONSTRAINT_RANGE) { + gdouble _tmp0_; + gdouble min; + gdouble _tmp1_; + gdouble max; + _tmp0_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->min); + min = _tmp0_; + _tmp1_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max); + max = _tmp1_; + if (v < min) { + v = min; + } + if (v > max) { + v = max; + } + } else { + if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) { + gdouble distance; + gdouble nearest; + distance = DBL_MAX; + nearest = 0.0; + { + gint i; + i = 0; + { + gboolean _tmp2_; + _tmp2_ = TRUE; + while (TRUE) { + gdouble _tmp3_; + gdouble x; + gdouble _tmp4_; + if (!_tmp2_) { + i++; + } + _tmp2_ = FALSE; + if (!(i < ((gint) option->constraint.word_list[0]))) { + break; + } + _tmp3_ = SANE_UNFIX ((SANE_Fixed) option->constraint.word_list[i + 1]); + x = _tmp3_; + _tmp4_ = fabs (x - v); + if (_tmp4_ < distance) { + gdouble _tmp5_; + _tmp5_ = fabs (x - v); + distance = _tmp5_; + nearest = x; + } + } + } + } + v = nearest; + } + } + _tmp6_ = SANE_FIX (v); + v_fixed = _tmp6_; + _tmp7_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, &v_fixed, NULL); + status = _tmp7_; + _tmp8_ = sane_status_to_string (status); + _tmp9_ = _tmp8_; + _tmp10_ = SANE_UNFIX (v_fixed); + g_debug ("scanner.vala:462: sane_control_option (%d, SANE_ACTION_SET_VALUE, %f) " \ +"-> (%s, %f)", (gint) option_index, value, _tmp9_, _tmp10_); + _g_free0 (_tmp9_); + _tmp11_ = SANE_UNFIX (v_fixed); + _result = _tmp11_; + if (_result_) { + *_result_ = _result; + } +} + + +static gchar string_get (const gchar* self, glong index) { + gchar result = '\0'; + g_return_val_if_fail (self != NULL, '\0'); + result = ((gchar*) self)[index]; + return result; +} + + +static gboolean scanner_set_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, const gchar* value, gchar** _result_) { + gchar* _result = NULL; + gboolean result = FALSE; + gchar* _tmp0_ = NULL; + gchar* s; + gint s_length1; + gint _s_size_; + gint i; + SANE_Status _tmp5_; + SANE_Status status; + gchar* _tmp6_; + gchar* _tmp7_ = NULL; + gchar* _tmp8_; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (option != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE); + _tmp0_ = g_new0 (gchar, option->size); + s = _tmp0_; + s_length1 = option->size; + _s_size_ = s_length1; + i = 0; + { + gboolean _tmp1_; + _tmp1_ = TRUE; + while (TRUE) { + gboolean _tmp2_ = FALSE; + gchar _tmp4_; + if (!_tmp1_) { + i++; + } + _tmp1_ = FALSE; + if (i < (option->size - 1)) { + gchar _tmp3_; + _tmp3_ = string_get (value, (glong) i); + _tmp2_ = _tmp3_ != '\0'; + } else { + _tmp2_ = FALSE; + } + if (!_tmp2_) { + break; + } + _tmp4_ = string_get (value, (glong) i); + s[i] = _tmp4_; + } + } + s[i] = '\0'; + _tmp5_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, s, NULL); + status = _tmp5_; + _tmp6_ = g_strdup ((const gchar*) s); + _g_free0 (_result); + _result = _tmp6_; + _tmp7_ = sane_status_to_string (status); + _tmp8_ = _tmp7_; + g_debug ("scanner.vala:478: sane_control_option (%d, SANE_ACTION_SET_VALUE, \"%s" \ +"\") -> (%s, \"%s\")", (gint) option_index, value, _tmp8_, _result); + _g_free0 (_tmp8_); + result = status == SANE_STATUS_GOOD; + s = (g_free (s), NULL); + if (_result_) { + *_result_ = _result; + } else { + _g_free0 (_result); + } + return result; +} + + +static gboolean scanner_set_constrained_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gchar** values, int values_length1, gchar** _result_) { + gchar* _result = NULL; + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (option != NULL, FALSE); + g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE); + g_return_val_if_fail (option->constraint_type == SANE_CONSTRAINT_STRING_LIST, FALSE); + { + gint i; + i = 0; + { + gboolean _tmp0_; + _tmp0_ = TRUE; + while (TRUE) { + gint j; + if (!_tmp0_) { + i++; + } + _tmp0_ = FALSE; + if (!(values[i] != NULL)) { + break; + } + j = 0; + { + gboolean _tmp1_; + _tmp1_ = TRUE; + while (TRUE) { + if (!_tmp1_) { + j++; + } + _tmp1_ = FALSE; + if (!(option->constraint.string_list[j] != NULL)) { + break; + } + if (g_strcmp0 (values[i], option->constraint.string_list[j]) == 0) { + break; + } + } + } + if (option->constraint.string_list[j] != NULL) { + gchar* _tmp2_ = NULL; + gboolean _tmp3_; + _tmp3_ = scanner_set_string_option (self, handle, option, option_index, values[i], &_tmp2_); + _g_free0 (_result); + _result = _tmp2_; + result = _tmp3_; + if (_result_) { + *_result_ = _result; + } else { + _g_free0 (_result); + } + return result; + } + } + } + } + result = FALSE; + if (_result_) { + *_result_ = _result; + } else { + _g_free0 (_result); + } + return result; +} + + +static void scanner_log_option (Scanner* self, SANE_Int index, const SANE_Option_Descriptor* option) { + gchar* _tmp0_ = NULL; + gchar* s; + gchar* _tmp16_ = NULL; + gchar* _tmp17_; + gchar* _tmp18_; + SANE_Int cap; + g_return_if_fail (self != NULL); + g_return_if_fail (option != NULL); + _tmp0_ = g_strdup_printf ("Option %d:", (gint) index); + s = _tmp0_; + if (g_strcmp0 (option->name, "") != 0) { + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + gchar* _tmp3_; + _tmp1_ = g_strdup_printf (" name='%s'", option->name); + _tmp2_ = _tmp1_; + _tmp3_ = g_strconcat (s, _tmp2_, NULL); + _g_free0 (s); + s = _tmp3_; + _g_free0 (_tmp2_); + } + if (g_strcmp0 (option->title, "") != 0) { + gchar* _tmp4_ = NULL; + gchar* _tmp5_; + gchar* _tmp6_; + _tmp4_ = g_strdup_printf (" title='%s'", option->title); + _tmp5_ = _tmp4_; + _tmp6_ = g_strconcat (s, _tmp5_, NULL); + _g_free0 (s); + s = _tmp6_; + _g_free0 (_tmp5_); + } + switch (option->type) { + case SANE_TYPE_BOOL: + { + gchar* _tmp7_; + _tmp7_ = g_strconcat (s, " type=bool", NULL); + _g_free0 (s); + s = _tmp7_; + break; + } + case SANE_TYPE_INT: + { + gchar* _tmp8_; + _tmp8_ = g_strconcat (s, " type=int", NULL); + _g_free0 (s); + s = _tmp8_; + break; + } + case SANE_TYPE_FIXED: + { + gchar* _tmp9_; + _tmp9_ = g_strconcat (s, " type=fixed", NULL); + _g_free0 (s); + s = _tmp9_; + break; + } + case SANE_TYPE_STRING: + { + gchar* _tmp10_; + _tmp10_ = g_strconcat (s, " type=string", NULL); + _g_free0 (s); + s = _tmp10_; + break; + } + case SANE_TYPE_BUTTON: + { + gchar* _tmp11_; + _tmp11_ = g_strconcat (s, " type=button", NULL); + _g_free0 (s); + s = _tmp11_; + break; + } + case SANE_TYPE_GROUP: + { + gchar* _tmp12_; + _tmp12_ = g_strconcat (s, " type=group", NULL); + _g_free0 (s); + s = _tmp12_; + break; + } + default: + { + gchar* _tmp13_ = NULL; + gchar* _tmp14_; + gchar* _tmp15_; + _tmp13_ = g_strdup_printf (" type=%d", (gint) option->type); + _tmp14_ = _tmp13_; + _tmp15_ = g_strconcat (s, _tmp14_, NULL); + _g_free0 (s); + s = _tmp15_; + _g_free0 (_tmp14_); + break; + } + } + _tmp16_ = g_strdup_printf (" size=%d", (gint) option->size); + _tmp17_ = _tmp16_; + _tmp18_ = g_strconcat (s, _tmp17_, NULL); + _g_free0 (s); + s = _tmp18_; + _g_free0 (_tmp17_); + switch (option->unit) { + case SANE_UNIT_NONE: + { + break; + } + case SANE_UNIT_PIXEL: + { + gchar* _tmp19_; + _tmp19_ = g_strconcat (s, " unit=pixels", NULL); + _g_free0 (s); + s = _tmp19_; + break; + } + case SANE_UNIT_BIT: + { + gchar* _tmp20_; + _tmp20_ = g_strconcat (s, " unit=bits", NULL); + _g_free0 (s); + s = _tmp20_; + break; + } + case SANE_UNIT_MM: + { + gchar* _tmp21_; + _tmp21_ = g_strconcat (s, " unit=mm", NULL); + _g_free0 (s); + s = _tmp21_; + break; + } + case SANE_UNIT_DPI: + { + gchar* _tmp22_; + _tmp22_ = g_strconcat (s, " unit=dpi", NULL); + _g_free0 (s); + s = _tmp22_; + break; + } + case SANE_UNIT_PERCENT: + { + gchar* _tmp23_; + _tmp23_ = g_strconcat (s, " unit=percent", NULL); + _g_free0 (s); + s = _tmp23_; + break; + } + case SANE_UNIT_MICROSECOND: + { + gchar* _tmp24_; + _tmp24_ = g_strconcat (s, " unit=microseconds", NULL); + _g_free0 (s); + s = _tmp24_; + break; + } + default: + { + gchar* _tmp25_ = NULL; + gchar* _tmp26_; + gchar* _tmp27_; + _tmp25_ = g_strdup_printf (" unit=%d", (gint) option->unit); + _tmp26_ = _tmp25_; + _tmp27_ = g_strconcat (s, _tmp26_, NULL); + _g_free0 (s); + s = _tmp27_; + _g_free0 (_tmp26_); + break; + } + } + switch (option->constraint_type) { + case SANE_CONSTRAINT_RANGE: + { + if (option->type == SANE_TYPE_FIXED) { + gdouble _tmp28_; + gdouble _tmp29_; + gchar* _tmp30_ = NULL; + gchar* _tmp31_; + gchar* _tmp32_; + _tmp28_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->min); + _tmp29_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max); + _tmp30_ = g_strdup_printf (" min=%f, max=%f, quant=%d", _tmp28_, _tmp29_, (gint) option->constraint.range->quant); + _tmp31_ = _tmp30_; + _tmp32_ = g_strconcat (s, _tmp31_, NULL); + _g_free0 (s); + s = _tmp32_; + _g_free0 (_tmp31_); + } else { + gchar* _tmp33_ = NULL; + gchar* _tmp34_; + gchar* _tmp35_; + _tmp33_ = g_strdup_printf (" min=%d, max=%d, quant=%d", (gint) option->constraint.range->min, (gint) option->constraint.range->max, (gint) option->constraint.range->quant); + _tmp34_ = _tmp33_; + _tmp35_ = g_strconcat (s, _tmp34_, NULL); + _g_free0 (s); + s = _tmp35_; + _g_free0 (_tmp34_); + } + break; + } + case SANE_CONSTRAINT_WORD_LIST: + { + gchar* _tmp36_; + gchar* _tmp46_; + _tmp36_ = g_strconcat (s, " values=[", NULL); + _g_free0 (s); + s = _tmp36_; + { + gint i; + i = 0; + { + gboolean _tmp37_; + _tmp37_ = TRUE; + while (TRUE) { + if (!_tmp37_) { + i++; + } + _tmp37_ = FALSE; + if (!(i < ((gint) option->constraint.word_list[0]))) { + break; + } + if (i != 0) { + gchar* _tmp38_; + _tmp38_ = g_strconcat (s, ", ", NULL); + _g_free0 (s); + s = _tmp38_; + } + if (option->type == SANE_TYPE_INT) { + gchar* _tmp39_ = NULL; + gchar* _tmp40_; + gchar* _tmp41_; + _tmp39_ = g_strdup_printf ("%d", (gint) option->constraint.word_list[i + 1]); + _tmp40_ = _tmp39_; + _tmp41_ = g_strconcat (s, _tmp40_, NULL); + _g_free0 (s); + s = _tmp41_; + _g_free0 (_tmp40_); + } else { + gdouble _tmp42_; + gchar* _tmp43_ = NULL; + gchar* _tmp44_; + gchar* _tmp45_; + _tmp42_ = SANE_UNFIX ((SANE_Fixed) option->constraint.word_list[i + 1]); + _tmp43_ = g_strdup_printf ("%f", _tmp42_); + _tmp44_ = _tmp43_; + _tmp45_ = g_strconcat (s, _tmp44_, NULL); + _g_free0 (s); + s = _tmp45_; + _g_free0 (_tmp44_); + } + } + } + } + _tmp46_ = g_strconcat (s, "]", NULL); + _g_free0 (s); + s = _tmp46_; + break; + } + case SANE_CONSTRAINT_STRING_LIST: + { + gchar* _tmp47_; + gchar* _tmp53_; + _tmp47_ = g_strconcat (s, " values=[", NULL); + _g_free0 (s); + s = _tmp47_; + { + gint i; + i = 0; + { + gboolean _tmp48_; + _tmp48_ = TRUE; + while (TRUE) { + gchar* _tmp50_ = NULL; + gchar* _tmp51_; + gchar* _tmp52_; + if (!_tmp48_) { + i++; + } + _tmp48_ = FALSE; + if (!(option->constraint.string_list[i] != NULL)) { + break; + } + if (i != 0) { + gchar* _tmp49_; + _tmp49_ = g_strconcat (s, ", ", NULL); + _g_free0 (s); + s = _tmp49_; + } + _tmp50_ = g_strdup_printf ("\"%s\"", option->constraint.string_list[i]); + _tmp51_ = _tmp50_; + _tmp52_ = g_strconcat (s, _tmp51_, NULL); + _g_free0 (s); + s = _tmp52_; + _g_free0 (_tmp51_); + } + } + } + _tmp53_ = g_strconcat (s, "]", NULL); + _g_free0 (s); + s = _tmp53_; + break; + } + default: + { + break; + } + } + cap = option->cap; + if (((gint) cap) != 0) { + gchar* _tmp54_; + _tmp54_ = g_strconcat (s, " cap=", NULL); + _g_free0 (s); + s = _tmp54_; + if (((gint) (cap & SANE_CAP_SOFT_SELECT)) != 0) { + gchar* _tmp56_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp55_; + _tmp55_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp55_; + } + _tmp56_ = g_strconcat (s, "soft-select", NULL); + _g_free0 (s); + s = _tmp56_; + cap = cap & (~SANE_CAP_SOFT_SELECT); + } + if (((gint) (cap & SANE_CAP_HARD_SELECT)) != 0) { + gchar* _tmp58_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp57_; + _tmp57_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp57_; + } + _tmp58_ = g_strconcat (s, "hard-select", NULL); + _g_free0 (s); + s = _tmp58_; + cap = cap & (~SANE_CAP_HARD_SELECT); + } + if (((gint) (cap & SANE_CAP_SOFT_DETECT)) != 0) { + gchar* _tmp60_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp59_; + _tmp59_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp59_; + } + _tmp60_ = g_strconcat (s, "soft-detect", NULL); + _g_free0 (s); + s = _tmp60_; + cap = cap & (~SANE_CAP_SOFT_DETECT); + } + if (((gint) (cap & SANE_CAP_EMULATED)) != 0) { + gchar* _tmp62_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp61_; + _tmp61_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp61_; + } + _tmp62_ = g_strconcat (s, "emulated", NULL); + _g_free0 (s); + s = _tmp62_; + cap = cap & (~SANE_CAP_EMULATED); + } + if (((gint) (cap & SANE_CAP_AUTOMATIC)) != 0) { + gchar* _tmp64_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp63_; + _tmp63_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp63_; + } + _tmp64_ = g_strconcat (s, "automatic", NULL); + _g_free0 (s); + s = _tmp64_; + cap = cap & (~SANE_CAP_AUTOMATIC); + } + if (((gint) (cap & SANE_CAP_INACTIVE)) != 0) { + gchar* _tmp66_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp65_; + _tmp65_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp65_; + } + _tmp66_ = g_strconcat (s, "inactive", NULL); + _g_free0 (s); + s = _tmp66_; + cap = cap & (~SANE_CAP_INACTIVE); + } + if (((gint) (cap & SANE_CAP_ADVANCED)) != 0) { + gchar* _tmp68_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp67_; + _tmp67_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp67_; + } + _tmp68_ = g_strconcat (s, "advanced", NULL); + _g_free0 (s); + s = _tmp68_; + cap = cap & (~SANE_CAP_ADVANCED); + } + if (((gint) cap) != 0) { + gchar* _tmp70_ = NULL; + gchar* _tmp71_; + gchar* _tmp72_; + if (g_strcmp0 (s, "") != 0) { + gchar* _tmp69_; + _tmp69_ = g_strconcat (s, ",", NULL); + _g_free0 (s); + s = _tmp69_; + } + _tmp70_ = g_strdup_printf ("%x", (guint) cap); + _tmp71_ = _tmp70_; + _tmp72_ = g_strconcat (s, _tmp71_, NULL); + _g_free0 (s); + s = _tmp72_; + _g_free0 (_tmp71_); + } + } + g_debug ("scanner.vala:665: %s", s); + if (option->desc != NULL) { + g_debug ("scanner.vala:668: Description: %s", option->desc); + } + _g_free0 (s); +} + + +static void scanner_authorization_cb (const gchar* resource, gchar* username, int username_length1, gchar* password, int password_length1) { + NotifyRequestAuthorization* _tmp0_ = NULL; + NotifyRequestAuthorization* _tmp1_; + gpointer _tmp2_ = NULL; + Credentials* credentials; + g_return_if_fail (resource != NULL); + _tmp0_ = notify_request_authorization_new (resource); + _tmp1_ = _tmp0_; + scanner_notify (scanner_scanner_object, (Notify*) _tmp1_); + _notify_unref0 (_tmp1_); + _tmp2_ = g_async_queue_pop (scanner_scanner_object->priv->authorize_queue); + credentials = (Credentials*) _tmp2_; + { + gint i; + i = 0; + { + gboolean _tmp3_; + _tmp3_ = TRUE; + while (TRUE) { + gboolean _tmp4_ = FALSE; + gchar _tmp5_; + gchar _tmp6_; + if (!_tmp3_) { + i++; + } + _tmp3_ = FALSE; + _tmp5_ = string_get (credentials->username, (glong) i); + if (_tmp5_ != '\0') { + _tmp4_ = i < SANE_MAX_USERNAME_LEN; + } else { + _tmp4_ = FALSE; + } + if (!_tmp4_) { + break; + } + _tmp6_ = string_get (credentials->username, (glong) i); + username[i] = _tmp6_; + } + } + } + { + gint i; + i = 0; + { + gboolean _tmp7_; + _tmp7_ = TRUE; + while (TRUE) { + gboolean _tmp8_ = FALSE; + gchar _tmp9_; + gchar _tmp10_; + if (!_tmp7_) { + i++; + } + _tmp7_ = FALSE; + _tmp9_ = string_get (credentials->password, (glong) i); + if (_tmp9_ != '\0') { + _tmp8_ = i < SANE_MAX_USERNAME_LEN; + } else { + _tmp8_ = FALSE; + } + if (!_tmp8_) { + break; + } + _tmp10_ = string_get (credentials->password, (glong) i); + password[i] = _tmp10_; + } + } + } + _credentials_unref0 (credentials); +} + + +static gpointer _credentials_ref0 (gpointer self) { + return self ? credentials_ref (self) : NULL; +} + + +void scanner_authorize (Scanner* self, const gchar* username, const gchar* password) { + Credentials* _tmp0_ = NULL; + Credentials* credentials; + gchar* _tmp1_; + gchar* _tmp2_; + Credentials* _tmp3_; + g_return_if_fail (self != NULL); + g_return_if_fail (username != NULL); + g_return_if_fail (password != NULL); + _tmp0_ = credentials_new (); + credentials = _tmp0_; + _tmp1_ = g_strdup (username); + _g_free0 (credentials->username); + credentials->username = _tmp1_; + _tmp2_ = g_strdup (password); + _g_free0 (credentials->password); + credentials->password = _tmp2_; + _tmp3_ = _credentials_ref0 (credentials); + g_async_queue_push (self->priv->authorize_queue, _tmp3_); + _credentials_unref0 (credentials); +} + + +static void scanner_close_device (Scanner* self) { + g_return_if_fail (self != NULL); + if (self->priv->have_handle) { + sane_cancel (self->priv->handle); + g_debug ("scanner.vala:695: sane_cancel ()"); + sane_close (self->priv->handle); + g_debug ("scanner.vala:698: sane_close ()"); + self->priv->have_handle = FALSE; + } + self->priv->buffer = (g_free (self->priv->buffer), NULL); + self->priv->buffer = NULL; + self->priv->buffer_length1 = 0; + self->priv->_buffer_size_ = self->priv->buffer_length1; + __g_list_free__scan_job_unref0_0 (self->priv->job_queue); + self->priv->job_queue = NULL; + scanner_set_scanning (self, FALSE); +} + + +static void scanner_fail_scan (Scanner* self, gint error_code, const gchar* error_string) { + NotifyScanFailed* _tmp0_ = NULL; + NotifyScanFailed* _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (error_string != NULL); + scanner_close_device (self); + self->priv->state = SCAN_STATE_IDLE; + _tmp0_ = notify_scan_failed_new (error_code, error_string); + _tmp1_ = _tmp0_; + scanner_notify (self, (Notify*) _tmp1_); + _notify_unref0 (_tmp1_); +} + + +static gpointer _request_ref0 (gpointer self) { + return self ? request_ref (self) : NULL; +} + + +static gpointer _scan_job_ref0 (gpointer self) { + return self ? scan_job_ref (self) : NULL; +} + + +static gboolean scanner_handle_requests (Scanner* self) { + gboolean result = FALSE; + gboolean _tmp0_ = FALSE; + gint request_count; + g_return_val_if_fail (self != NULL, FALSE); + if (self->priv->state == SCAN_STATE_IDLE) { + _tmp0_ = self->priv->need_redetect; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + self->priv->state = SCAN_STATE_REDETECT; + } + request_count = 0; + while (TRUE) { + Request* request = NULL; + gboolean _tmp1_ = FALSE; + gboolean _tmp2_ = FALSE; + if (self->priv->state == SCAN_STATE_IDLE) { + _tmp2_ = request_count == 0; + } else { + _tmp2_ = FALSE; + } + if (_tmp2_) { + _tmp1_ = TRUE; + } else { + gint _tmp3_; + _tmp3_ = g_async_queue_length (self->priv->request_queue); + _tmp1_ = _tmp3_ > 0; + } + if (_tmp1_) { + gpointer _tmp4_ = NULL; + _tmp4_ = g_async_queue_pop (self->priv->request_queue); + _request_unref0 (request); + request = (Request*) _tmp4_; + } else { + result = TRUE; + _request_unref0 (request); + return result; + } + g_debug ("scanner.vala:732: Processing request"); + request_count++; + if (IS_REQUEST_START_SCAN (request)) { + RequestStartScan* _tmp5_; + RequestStartScan* r; + ScanJob* _tmp6_; + _tmp5_ = _request_ref0 (REQUEST_START_SCAN (request)); + r = _tmp5_; + _tmp6_ = _scan_job_ref0 (r->job); + self->priv->job_queue = g_list_append (self->priv->job_queue, _tmp6_); + _request_unref0 (r); + } else { + if (IS_REQUEST_CANCEL (request)) { + scanner_fail_scan (self, (gint) SANE_STATUS_CANCELLED, "Scan cancelled - do not report this error"); + } else { + if (IS_REQUEST_QUIT (request)) { + scanner_close_device (self); + result = FALSE; + _request_unref0 (request); + return result; + } + } + } + _request_unref0 (request); + } +} + + +static void scanner_do_open (Scanner* self) { + ScanJob* _tmp0_; + ScanJob* job; + gboolean _tmp1_ = FALSE; + SANE_Handle _tmp4_; + SANE_Status _tmp5_; + SANE_Status status; + gchar* _tmp6_ = NULL; + gchar* _tmp7_; + gchar* _tmp10_; + g_return_if_fail (self != NULL); + _tmp0_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data)); + job = _tmp0_; + self->priv->line_count = 0; + self->priv->pass_number = 0; + self->priv->page_number = 0; + self->priv->notified_page = -1; + self->priv->option_index = (SANE_Int) 0; + self->priv->br_x_option_index = (SANE_Int) 0; + self->priv->br_y_option_index = (SANE_Int) 0; + if (job->device == NULL) { + _tmp1_ = self->priv->default_device != NULL; + } else { + _tmp1_ = FALSE; + } + if (_tmp1_) { + gchar* _tmp2_; + _tmp2_ = g_strdup (self->priv->default_device); + _g_free0 (job->device); + job->device = _tmp2_; + } + if (job->device == NULL) { + const gchar* _tmp3_ = NULL; + g_warning ("scanner.vala:769: No scan device available"); + _tmp3_ = _ ("No scanners available. Please connect a scanner."); + scanner_fail_scan (self, 0, _tmp3_); + _scan_job_unref0 (job); + return; + } + if (self->priv->have_handle) { + if (g_strcmp0 (self->priv->current_device, job->device) == 0) { + self->priv->state = SCAN_STATE_GET_OPTION; + _scan_job_unref0 (job); + return; + } + sane_close (self->priv->handle); + g_debug ("scanner.vala:786: sane_close ()"); + self->priv->have_handle = FALSE; + } + _g_free0 (self->priv->current_device); + self->priv->current_device = NULL; + self->priv->have_handle = FALSE; + _tmp5_ = sane_open (job->device, &_tmp4_); + self->priv->handle = _tmp4_; + status = _tmp5_; + _tmp6_ = sane_status_to_string (status); + _tmp7_ = _tmp6_; + g_debug ("scanner.vala:794: sane_open (\"%s\") -> %s", job->device, _tmp7_); + _g_free0 (_tmp7_); + if (status != SANE_STATUS_GOOD) { + const gchar* _tmp8_ = NULL; + const gchar* _tmp9_ = NULL; + _tmp8_ = sane_strstatus (status); + g_warning ("scanner.vala:798: Unable to get open device: %s", _tmp8_); + _tmp9_ = _ ("Unable to connect to scanner"); + scanner_fail_scan (self, (gint) status, _tmp9_); + _scan_job_unref0 (job); + return; + } + self->priv->have_handle = TRUE; + _tmp10_ = g_strdup (job->device); + _g_free0 (self->priv->current_device); + self->priv->current_device = _tmp10_; + self->priv->state = SCAN_STATE_GET_OPTION; + _scan_job_unref0 (job); +} + + +static void scanner_do_get_option (Scanner* self) { + ScanJob* _tmp0_; + ScanJob* job; + const SANE_Option_Descriptor* _tmp1_ = NULL; + const SANE_Option_Descriptor* option; + SANE_Int index; + g_return_if_fail (self != NULL); + _tmp0_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data)); + job = _tmp0_; + _tmp1_ = sane_get_option_descriptor (self->priv->handle, self->priv->option_index); + option = _tmp1_; + g_debug ("scanner.vala:815: sane_get_option_descriptor (%d)", (gint) self->priv->option_index); + index = self->priv->option_index; + self->priv->option_index++; + if (option == NULL) { + if (((gint) self->priv->br_x_option_index) != 0) { + const SANE_Option_Descriptor* _tmp2_ = NULL; + _tmp2_ = sane_get_option_descriptor (self->priv->handle, self->priv->br_x_option_index); + option = _tmp2_; + g_debug ("scanner.vala:825: sane_get_option_descriptor (%d)", (gint) self->priv->br_x_option_index); + if (option->constraint_type == SANE_CONSTRAINT_RANGE) { + if (option->type == SANE_TYPE_FIXED) { + gdouble _tmp3_; + _tmp3_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max); + scanner_set_fixed_option (self, self->priv->handle, option, self->priv->br_x_option_index, _tmp3_, NULL); + } else { + scanner_set_int_option (self, self->priv->handle, option, self->priv->br_x_option_index, (gint) option->constraint.range->max, NULL); + } + } + } + if (((gint) self->priv->br_y_option_index) != 0) { + const SANE_Option_Descriptor* _tmp4_ = NULL; + _tmp4_ = sane_get_option_descriptor (self->priv->handle, self->priv->br_y_option_index); + option = _tmp4_; + g_debug ("scanner.vala:837: sane_get_option_descriptor (%d)", (gint) self->priv->br_y_option_index); + if (option->constraint_type == SANE_CONSTRAINT_RANGE) { + if (option->type == SANE_TYPE_FIXED) { + gdouble _tmp5_; + _tmp5_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max); + scanner_set_fixed_option (self, self->priv->handle, option, self->priv->br_y_option_index, _tmp5_, NULL); + } else { + scanner_set_int_option (self, self->priv->handle, option, self->priv->br_y_option_index, (gint) option->constraint.range->max, NULL); + } + } + } + self->priv->state = SCAN_STATE_START; + _scan_job_unref0 (job); + return; + } + scanner_log_option (self, index, option); + if (option->type == SANE_TYPE_GROUP) { + _scan_job_unref0 (job); + return; + } + if (((gint) (option->cap & SANE_CAP_INACTIVE)) != 0) { + _scan_job_unref0 (job); + return; + } + if (option->name == NULL) { + _scan_job_unref0 (job); + return; + } + if (g_strcmp0 (option->name, SANE_NAME_SCAN_RESOLUTION) == 0) { + if (option->type == SANE_TYPE_FIXED) { + gdouble _tmp6_; + scanner_set_fixed_option (self, self->priv->handle, option, index, job->dpi, &_tmp6_); + job->dpi = _tmp6_; + } else { + gint dpi = 0; + gint _tmp7_; + scanner_set_int_option (self, self->priv->handle, option, index, (gint) job->dpi, &_tmp7_); + dpi = _tmp7_; + job->dpi = (gdouble) dpi; + } + } else { + if (g_strcmp0 (option->name, SANE_NAME_SCAN_SOURCE) == 0) { + gchar* _tmp8_; + const gchar* _tmp9_ = NULL; + gchar* _tmp10_; + gchar* _tmp11_; + const gchar* _tmp12_ = NULL; + gchar* _tmp13_; + gchar* _tmp14_; + gchar* _tmp15_; + const gchar* _tmp16_ = NULL; + gchar* _tmp17_; + gchar** _tmp18_ = NULL; + gchar** flatbed_sources; + gint flatbed_sources_length1; + gint _flatbed_sources_size_; + gchar* _tmp19_; + const gchar* _tmp20_ = NULL; + gchar* _tmp21_; + gchar* _tmp22_; + gchar* _tmp23_; + gchar* _tmp24_; + gchar** _tmp25_ = NULL; + gchar** adf_sources; + gint adf_sources_length1; + gint _adf_sources_size_; + gchar* _tmp26_; + const gchar* _tmp27_ = NULL; + gchar* _tmp28_; + gchar** _tmp29_ = NULL; + gchar** adf_front_sources; + gint adf_front_sources_length1; + gint _adf_front_sources_size_; + gchar* _tmp30_; + const gchar* _tmp31_ = NULL; + gchar* _tmp32_; + gchar** _tmp33_ = NULL; + gchar** adf_back_sources; + gint adf_back_sources_length1; + gint _adf_back_sources_size_; + gchar* _tmp34_; + const gchar* _tmp35_ = NULL; + gchar* _tmp36_; + gchar** _tmp37_ = NULL; + gchar** adf_duplex_sources; + gint adf_duplex_sources_length1; + gint _adf_duplex_sources_size_; + _tmp8_ = g_strdup ("Auto"); + _tmp9_ = SANE_I18N ("Auto"); + _tmp10_ = g_strdup (_tmp9_); + _tmp11_ = g_strdup ("Flatbed"); + _tmp12_ = SANE_I18N ("Flatbed"); + _tmp13_ = g_strdup (_tmp12_); + _tmp14_ = g_strdup ("FlatBed"); + _tmp15_ = g_strdup ("Normal"); + _tmp16_ = SANE_I18N ("Normal"); + _tmp17_ = g_strdup (_tmp16_); + _tmp18_ = g_new0 (gchar*, 7 + 1); + _tmp18_[0] = _tmp8_; + _tmp18_[1] = _tmp10_; + _tmp18_[2] = _tmp11_; + _tmp18_[3] = _tmp13_; + _tmp18_[4] = _tmp14_; + _tmp18_[5] = _tmp15_; + _tmp18_[6] = _tmp17_; + flatbed_sources = _tmp18_; + flatbed_sources_length1 = 7; + _flatbed_sources_size_ = flatbed_sources_length1; + _tmp19_ = g_strdup ("Automatic Document Feeder"); + _tmp20_ = SANE_I18N ("Automatic Document Feeder"); + _tmp21_ = g_strdup (_tmp20_); + _tmp22_ = g_strdup ("ADF"); + _tmp23_ = g_strdup ("Automatic Document Feeder(left aligned)"); + _tmp24_ = g_strdup ("Automatic Document Feeder(centrally aligned)"); + _tmp25_ = g_new0 (gchar*, 5 + 1); + _tmp25_[0] = _tmp19_; + _tmp25_[1] = _tmp21_; + _tmp25_[2] = _tmp22_; + _tmp25_[3] = _tmp23_; + _tmp25_[4] = _tmp24_; + adf_sources = _tmp25_; + adf_sources_length1 = 5; + _adf_sources_size_ = adf_sources_length1; + _tmp26_ = g_strdup ("ADF Front"); + _tmp27_ = SANE_I18N ("ADF Front"); + _tmp28_ = g_strdup (_tmp27_); + _tmp29_ = g_new0 (gchar*, 2 + 1); + _tmp29_[0] = _tmp26_; + _tmp29_[1] = _tmp28_; + adf_front_sources = _tmp29_; + adf_front_sources_length1 = 2; + _adf_front_sources_size_ = adf_front_sources_length1; + _tmp30_ = g_strdup ("ADF Back"); + _tmp31_ = SANE_I18N ("ADF Back"); + _tmp32_ = g_strdup (_tmp31_); + _tmp33_ = g_new0 (gchar*, 2 + 1); + _tmp33_[0] = _tmp30_; + _tmp33_[1] = _tmp32_; + adf_back_sources = _tmp33_; + adf_back_sources_length1 = 2; + _adf_back_sources_size_ = adf_back_sources_length1; + _tmp34_ = g_strdup ("ADF Duplex"); + _tmp35_ = SANE_I18N ("ADF Duplex"); + _tmp36_ = g_strdup (_tmp35_); + _tmp37_ = g_new0 (gchar*, 2 + 1); + _tmp37_[0] = _tmp34_; + _tmp37_[1] = _tmp36_; + adf_duplex_sources = _tmp37_; + adf_duplex_sources_length1 = 2; + _adf_duplex_sources_size_ = adf_duplex_sources_length1; + switch (job->type) { + case SCAN_TYPE_SINGLE: + { + gboolean _tmp38_; + _tmp38_ = scanner_set_default_option (self, self->priv->handle, option, index); + if (!_tmp38_) { + gboolean _tmp39_; + _tmp39_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, flatbed_sources, flatbed_sources_length1, NULL); + if (!_tmp39_) { + g_warning ("scanner.vala:921: Unable to set single page source, please file a bug"); + } + } + break; + } + case SCAN_TYPE_ADF_FRONT: + { + gboolean _tmp40_; + _tmp40_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_front_sources, adf_front_sources_length1, NULL); + if (!_tmp40_) { + gboolean _tmp41_; + _tmp41_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_sources, adf_sources_length1, NULL); + if (!(!_tmp41_)) { + g_warning ("scanner.vala:926: Unable to set front ADF source, please file a bug"); + } + } + break; + } + case SCAN_TYPE_ADF_BACK: + { + gboolean _tmp42_; + _tmp42_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_back_sources, adf_back_sources_length1, NULL); + if (!_tmp42_) { + gboolean _tmp43_; + _tmp43_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_sources, adf_sources_length1, NULL); + if (!_tmp43_) { + g_warning ("scanner.vala:931: Unable to set back ADF source, please file a bug"); + } + } + break; + } + case SCAN_TYPE_ADF_BOTH: + { + gboolean _tmp44_; + _tmp44_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_duplex_sources, adf_duplex_sources_length1, NULL); + if (!_tmp44_) { + gboolean _tmp45_; + _tmp45_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_sources, adf_sources_length1, NULL); + if (!_tmp45_) { + g_warning ("scanner.vala:936: Unable to set duplex ADF source, please file a bug"); + } + } + break; + } + default: + break; + } + adf_duplex_sources = (_vala_array_free (adf_duplex_sources, adf_duplex_sources_length1, (GDestroyNotify) g_free), NULL); + adf_back_sources = (_vala_array_free (adf_back_sources, adf_back_sources_length1, (GDestroyNotify) g_free), NULL); + adf_front_sources = (_vala_array_free (adf_front_sources, adf_front_sources_length1, (GDestroyNotify) g_free), NULL); + adf_sources = (_vala_array_free (adf_sources, adf_sources_length1, (GDestroyNotify) g_free), NULL); + flatbed_sources = (_vala_array_free (flatbed_sources, flatbed_sources_length1, (GDestroyNotify) g_free), NULL); + } else { + if (g_strcmp0 (option->name, "duplex") == 0) { + if (option->type == SANE_TYPE_BOOL) { + scanner_set_bool_option (self, self->priv->handle, option, index, job->type == SCAN_TYPE_ADF_BOTH, NULL); + } + } else { + if (g_strcmp0 (option->name, "batch-scan") == 0) { + if (option->type == SANE_TYPE_BOOL) { + scanner_set_bool_option (self, self->priv->handle, option, index, job->type != SCAN_TYPE_SINGLE, NULL); + } + } else { + if (g_strcmp0 (option->name, SANE_NAME_BIT_DEPTH) == 0) { + if (job->depth > 0) { + scanner_set_int_option (self, self->priv->handle, option, index, job->depth, NULL); + } + } else { + if (g_strcmp0 (option->name, SANE_NAME_SCAN_MODE) == 0) { + gchar* _tmp46_; + gchar* _tmp47_; + gchar* _tmp48_; + gchar** _tmp49_ = NULL; + gchar** color_scan_modes; + gint color_scan_modes_length1; + gint _color_scan_modes_size_; + gchar* _tmp50_; + gchar* _tmp51_; + gchar* _tmp52_; + const gchar* _tmp53_ = NULL; + gchar* _tmp54_; + gchar* _tmp55_; + gchar** _tmp56_ = NULL; + gchar** gray_scan_modes; + gint gray_scan_modes_length1; + gint _gray_scan_modes_size_; + gchar* _tmp57_; + gchar* _tmp58_; + gchar* _tmp59_; + const gchar* _tmp60_ = NULL; + gchar* _tmp61_; + gchar* _tmp62_; + const gchar* _tmp63_ = NULL; + gchar* _tmp64_; + gchar* _tmp65_; + const gchar* _tmp66_ = NULL; + gchar* _tmp67_; + gchar* _tmp68_; + gchar* _tmp69_; + gchar* _tmp70_; + gchar* _tmp71_; + const gchar* _tmp72_ = NULL; + gchar* _tmp73_; + gchar* _tmp74_; + gchar** _tmp75_ = NULL; + gchar** lineart_scan_modes; + gint lineart_scan_modes_length1; + gint _lineart_scan_modes_size_; + _tmp46_ = g_strdup (SANE_VALUE_SCAN_MODE_COLOR); + _tmp47_ = g_strdup ("Color"); + _tmp48_ = g_strdup ("24bit Color"); + _tmp49_ = g_new0 (gchar*, 3 + 1); + _tmp49_[0] = _tmp46_; + _tmp49_[1] = _tmp47_; + _tmp49_[2] = _tmp48_; + color_scan_modes = _tmp49_; + color_scan_modes_length1 = 3; + _color_scan_modes_size_ = color_scan_modes_length1; + _tmp50_ = g_strdup (SANE_VALUE_SCAN_MODE_GRAY); + _tmp51_ = g_strdup ("Gray"); + _tmp52_ = g_strdup ("Grayscale"); + _tmp53_ = SANE_I18N ("Grayscale"); + _tmp54_ = g_strdup (_tmp53_); + _tmp55_ = g_strdup ("True Gray"); + _tmp56_ = g_new0 (gchar*, 5 + 1); + _tmp56_[0] = _tmp50_; + _tmp56_[1] = _tmp51_; + _tmp56_[2] = _tmp52_; + _tmp56_[3] = _tmp54_; + _tmp56_[4] = _tmp55_; + gray_scan_modes = _tmp56_; + gray_scan_modes_length1 = 5; + _gray_scan_modes_size_ = gray_scan_modes_length1; + _tmp57_ = g_strdup (SANE_VALUE_SCAN_MODE_LINEART); + _tmp58_ = g_strdup ("Lineart"); + _tmp59_ = g_strdup ("LineArt"); + _tmp60_ = SANE_I18N ("LineArt"); + _tmp61_ = g_strdup (_tmp60_); + _tmp62_ = g_strdup ("Black & White"); + _tmp63_ = SANE_I18N ("Black & White"); + _tmp64_ = g_strdup (_tmp63_); + _tmp65_ = g_strdup ("Binary"); + _tmp66_ = SANE_I18N ("Binary"); + _tmp67_ = g_strdup (_tmp66_); + _tmp68_ = g_strdup ("Thresholded"); + _tmp69_ = g_strdup (SANE_VALUE_SCAN_MODE_GRAY); + _tmp70_ = g_strdup ("Gray"); + _tmp71_ = g_strdup ("Grayscale"); + _tmp72_ = SANE_I18N ("Grayscale"); + _tmp73_ = g_strdup (_tmp72_); + _tmp74_ = g_strdup ("True Gray"); + _tmp75_ = g_new0 (gchar*, 14 + 1); + _tmp75_[0] = _tmp57_; + _tmp75_[1] = _tmp58_; + _tmp75_[2] = _tmp59_; + _tmp75_[3] = _tmp61_; + _tmp75_[4] = _tmp62_; + _tmp75_[5] = _tmp64_; + _tmp75_[6] = _tmp65_; + _tmp75_[7] = _tmp67_; + _tmp75_[8] = _tmp68_; + _tmp75_[9] = _tmp69_; + _tmp75_[10] = _tmp70_; + _tmp75_[11] = _tmp71_; + _tmp75_[12] = _tmp73_; + _tmp75_[13] = _tmp74_; + lineart_scan_modes = _tmp75_; + lineart_scan_modes_length1 = 14; + _lineart_scan_modes_size_ = lineart_scan_modes_length1; + switch (job->scan_mode) { + case SCAN_MODE_COLOR: + { + gboolean _tmp76_; + _tmp76_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, color_scan_modes, color_scan_modes_length1, NULL); + if (!_tmp76_) { + g_warning ("scanner.vala:994: Unable to set Color mode, please file a bug"); + } + break; + } + case SCAN_MODE_GRAY: + { + gboolean _tmp77_; + _tmp77_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, gray_scan_modes, gray_scan_modes_length1, NULL); + if (!_tmp77_) { + g_warning ("scanner.vala:998: Unable to set Gray mode, please file a bug"); + } + break; + } + case SCAN_MODE_LINEART: + { + gboolean _tmp78_; + _tmp78_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, lineart_scan_modes, lineart_scan_modes_length1, NULL); + if (!_tmp78_) { + g_warning ("scanner.vala:1002: Unable to set Lineart mode, please file a bug"); + } + break; + } + default: + { + break; + } + } + lineart_scan_modes = (_vala_array_free (lineart_scan_modes, lineart_scan_modes_length1, (GDestroyNotify) g_free), NULL); + gray_scan_modes = (_vala_array_free (gray_scan_modes, gray_scan_modes_length1, (GDestroyNotify) g_free), NULL); + color_scan_modes = (_vala_array_free (color_scan_modes, color_scan_modes_length1, (GDestroyNotify) g_free), NULL); + } else { + if (g_strcmp0 (option->name, "compression") == 0) { + const gchar* _tmp79_ = NULL; + gchar* _tmp80_; + const gchar* _tmp81_ = NULL; + gchar* _tmp82_; + gchar* _tmp83_; + gchar* _tmp84_; + gchar** _tmp85_ = NULL; + gchar** disable_compression_names; + gint disable_compression_names_length1; + gint _disable_compression_names_size_; + gboolean _tmp86_; + _tmp79_ = SANE_I18N ("None"); + _tmp80_ = g_strdup (_tmp79_); + _tmp81_ = SANE_I18N ("none"); + _tmp82_ = g_strdup (_tmp81_); + _tmp83_ = g_strdup ("None"); + _tmp84_ = g_strdup ("none"); + _tmp85_ = g_new0 (gchar*, 4 + 1); + _tmp85_[0] = _tmp80_; + _tmp85_[1] = _tmp82_; + _tmp85_[2] = _tmp83_; + _tmp85_[3] = _tmp84_; + disable_compression_names = _tmp85_; + disable_compression_names_length1 = 4; + _disable_compression_names_size_ = disable_compression_names_length1; + _tmp86_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, disable_compression_names, disable_compression_names_length1, NULL); + if (!_tmp86_) { + g_warning ("scanner.vala:1020: Unable to disable compression, please file a bug"); + } + disable_compression_names = (_vala_array_free (disable_compression_names, disable_compression_names_length1, (GDestroyNotify) g_free), NULL); + } else { + if (g_strcmp0 (option->name, SANE_NAME_SCAN_BR_X) == 0) { + self->priv->br_x_option_index = index; + } else { + if (g_strcmp0 (option->name, SANE_NAME_SCAN_BR_Y) == 0) { + self->priv->br_y_option_index = index; + } else { + if (g_strcmp0 (option->name, SANE_NAME_PAGE_WIDTH) == 0) { + if (((gdouble) job->page_width) > 0.0) { + if (option->type == SANE_TYPE_FIXED) { + scanner_set_fixed_option (self, self->priv->handle, option, index, job->page_width / 10.0, NULL); + } else { + scanner_set_int_option (self, self->priv->handle, option, index, job->page_width / 10, NULL); + } + } + } else { + if (g_strcmp0 (option->name, SANE_NAME_PAGE_HEIGHT) == 0) { + if (((gdouble) job->page_height) > 0.0) { + if (option->type == SANE_TYPE_FIXED) { + scanner_set_fixed_option (self, self->priv->handle, option, index, job->page_height / 10.0, NULL); + } else { + scanner_set_int_option (self, self->priv->handle, option, index, job->page_height / 10, NULL); + } + } + } + } + } + } + } + } + } + } + } + } + } + if (g_strcmp0 (self->priv->current_device, "test") == 0) { + if (g_strcmp0 (option->name, "hand-scanner") == 0) { + scanner_set_bool_option (self, self->priv->handle, option, index, FALSE, NULL); + } else { + if (g_strcmp0 (option->name, "three-pass") == 0) { + scanner_set_bool_option (self, self->priv->handle, option, index, FALSE, NULL); + } else { + if (g_strcmp0 (option->name, "test-picture") == 0) { + scanner_set_string_option (self, self->priv->handle, option, index, "Color pattern", NULL); + } else { + if (g_strcmp0 (option->name, "read-delay") == 0) { + scanner_set_bool_option (self, self->priv->handle, option, index, TRUE, NULL); + } else { + if (g_strcmp0 (option->name, "read-delay-duration") == 0) { + scanner_set_int_option (self, self->priv->handle, option, index, 200000, NULL); + } + } + } + } + } + } + _scan_job_unref0 (job); +} + + +static void scanner_do_complete_document (Scanner* self) { + NotifyDocumentDone* _tmp0_ = NULL; + NotifyDocumentDone* _tmp1_; + g_return_if_fail (self != NULL); + self->priv->job_queue = g_list_remove_link (self->priv->job_queue, self->priv->job_queue); + self->priv->state = SCAN_STATE_IDLE; + if (self->priv->job_queue != NULL) { + self->priv->state = SCAN_STATE_OPEN; + return; + } + _tmp0_ = notify_document_done_new (); + _tmp1_ = _tmp0_; + scanner_notify (self, (Notify*) _tmp1_); + _notify_unref0 (_tmp1_); + scanner_set_scanning (self, FALSE); +} + + +static void scanner_do_start (Scanner* self) { + SANE_Status status = 0; + NotifyExpectPage* _tmp0_ = NULL; + NotifyExpectPage* _tmp1_; + SANE_Status _tmp2_; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + g_return_if_fail (self != NULL); + _tmp0_ = notify_expect_page_new (); + _tmp1_ = _tmp0_; + scanner_notify (self, (Notify*) _tmp1_); + _notify_unref0 (_tmp1_); + _tmp2_ = sane_start (self->priv->handle); + status = _tmp2_; + _tmp3_ = sane_status_to_string (status); + _tmp4_ = _tmp3_; + g_debug ("scanner.vala:1090: sane_start (page=%d, pass=%d) -> %s", self->priv->page_number, self->priv->pass_number, _tmp4_); + _g_free0 (_tmp4_); + if (status == SANE_STATUS_GOOD) { + self->priv->state = SCAN_STATE_GET_PARAMETERS; + } else { + if (status == SANE_STATUS_NO_DOCS) { + scanner_do_complete_document (self); + } else { + const gchar* _tmp5_ = NULL; + const gchar* _tmp6_ = NULL; + _tmp5_ = sane_strstatus (status); + g_warning ("scanner.vala:1097: Unable to start device: %s", _tmp5_); + _tmp6_ = _ ("Unable to start scan"); + scanner_fail_scan (self, (gint) status, _tmp6_); + } + } +} + + +static gchar* sane_frame_to_string (SANE_Frame frame) { + gchar* result = NULL; + switch (frame) { + case SANE_FRAME_GRAY: + { + gchar* _tmp0_; + _tmp0_ = g_strdup ("SANE_FRAME_GRAY"); + result = _tmp0_; + return result; + } + case SANE_FRAME_RGB: + { + gchar* _tmp1_; + _tmp1_ = g_strdup ("SANE_FRAME_RGB"); + result = _tmp1_; + return result; + } + case SANE_FRAME_RED: + { + gchar* _tmp2_; + _tmp2_ = g_strdup ("SANE_FRAME_RED"); + result = _tmp2_; + return result; + } + case SANE_FRAME_GREEN: + { + gchar* _tmp3_; + _tmp3_ = g_strdup ("SANE_FRAME_GREEN"); + result = _tmp3_; + return result; + } + case SANE_FRAME_BLUE: + { + gchar* _tmp4_; + _tmp4_ = g_strdup ("SANE_FRAME_BLUE"); + result = _tmp4_; + return result; + } + default: + { + gchar* _tmp5_ = NULL; + _tmp5_ = g_strdup_printf ("SANE_FRAME(%d)", (gint) frame); + result = _tmp5_; + return result; + } + } +} + + +static void scanner_do_get_parameters (Scanner* self) { + SANE_Parameters _tmp0_ = {0}; + SANE_Status _tmp1_; + SANE_Status status; + gchar* _tmp2_ = NULL; + gchar* _tmp3_; + ScanJob* _tmp6_; + ScanJob* job; + const gchar* _tmp7_ = NULL; + gchar* _tmp8_ = NULL; + gchar* _tmp9_; + ScanPageInfo* _tmp10_ = NULL; + ScanPageInfo* info; + gboolean _tmp11_ = FALSE; + gboolean _tmp12_ = FALSE; + gboolean _tmp13_ = FALSE; + gint _tmp14_ = 0; + gchar* _tmp15_; + gint buffer_size; + guchar* _tmp18_ = NULL; + g_return_if_fail (self != NULL); + _tmp1_ = sane_get_parameters (self->priv->handle, &_tmp0_); + self->priv->parameters = _tmp0_; + status = _tmp1_; + _tmp2_ = sane_status_to_string (status); + _tmp3_ = _tmp2_; + g_debug ("scanner.vala:1107: sane_get_parameters () -> %s", _tmp3_); + _g_free0 (_tmp3_); + if (status != SANE_STATUS_GOOD) { + const gchar* _tmp4_ = NULL; + const gchar* _tmp5_ = NULL; + _tmp4_ = sane_strstatus (status); + g_warning ("scanner.vala:1110: Unable to get device parameters: %s", _tmp4_); + _tmp5_ = _ ("Error communicating with scanner"); + scanner_fail_scan (self, (gint) status, _tmp5_); + return; + } + _tmp6_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data)); + job = _tmp6_; + if (self->priv->parameters.last_frame) { + _tmp7_ = "SANE_TRUE"; + } else { + _tmp7_ = "SANE_FALSE"; + } + _tmp8_ = sane_frame_to_string (self->priv->parameters.format); + _tmp9_ = _tmp8_; + g_debug ("scanner.vala:1119: Parameters: format=%s last_frame=%s bytes_per_line=" \ +"%d pixels_per_line=%d lines=%d depth=%d", _tmp9_, _tmp7_, self->priv->parameters.bytes_per_line, self->priv->parameters.pixels_per_line, self->priv->parameters.lines, self->priv->parameters.depth); + _g_free0 (_tmp9_); + _tmp10_ = scan_page_info_new (); + info = _tmp10_; + info->width = self->priv->parameters.pixels_per_line; + info->height = self->priv->parameters.lines; + info->depth = self->priv->parameters.depth; + if (self->priv->parameters.depth == 8) { + _tmp13_ = self->priv->parameters.format == SANE_FRAME_GRAY; + } else { + _tmp13_ = FALSE; + } + if (_tmp13_) { + _tmp12_ = job->depth == 2; + } else { + _tmp12_ = FALSE; + } + if (_tmp12_) { + _tmp11_ = job->scan_mode == SCAN_MODE_GRAY; + } else { + _tmp11_ = FALSE; + } + if (_tmp11_) { + info->depth = job->depth; + } + if (self->priv->parameters.format == SANE_FRAME_GRAY) { + _tmp14_ = 1; + } else { + _tmp14_ = 3; + } + info->n_channels = _tmp14_; + info->dpi = job->dpi; + _tmp15_ = g_strdup (self->priv->current_device); + _g_free0 (info->device); + info->device = _tmp15_; + if (self->priv->page_number != self->priv->notified_page) { + NotifyGotPageInfo* _tmp16_ = NULL; + NotifyGotPageInfo* _tmp17_; + _tmp16_ = notify_got_page_info_new (info); + _tmp17_ = _tmp16_; + scanner_notify (self, (Notify*) _tmp17_); + _notify_unref0 (_tmp17_); + self->priv->notified_page = self->priv->page_number; + } + buffer_size = self->priv->parameters.bytes_per_line + 1; + _tmp18_ = g_new0 (guchar, buffer_size); + self->priv->buffer = (g_free (self->priv->buffer), NULL); + self->priv->buffer = _tmp18_; + self->priv->buffer_length1 = buffer_size; + self->priv->_buffer_size_ = self->priv->buffer_length1; + self->priv->n_used = 0; + self->priv->line_count = 0; + self->priv->pass_number = 0; + self->priv->state = SCAN_STATE_READ; + _scan_page_info_unref0 (info); + _scan_job_unref0 (job); +} + + +static void scanner_do_complete_page (Scanner* self) { + NotifyPageDone* _tmp0_ = NULL; + NotifyPageDone* _tmp1_; + ScanJob* _tmp2_; + ScanJob* job; + g_return_if_fail (self != NULL); + _tmp0_ = notify_page_done_new (); + _tmp1_ = _tmp0_; + scanner_notify (self, (Notify*) _tmp1_); + _notify_unref0 (_tmp1_); + _tmp2_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data)); + job = _tmp2_; + if (!self->priv->parameters.last_frame) { + self->priv->pass_number++; + self->priv->state = SCAN_STATE_START; + _scan_job_unref0 (job); + return; + } + if (job->type != SCAN_TYPE_SINGLE) { + NotifyPageDone* _tmp3_ = NULL; + NotifyPageDone* _tmp4_; + self->priv->page_number++; + self->priv->pass_number = 0; + _tmp3_ = notify_page_done_new (); + _tmp4_ = _tmp3_; + scanner_notify (self, (Notify*) _tmp4_); + _notify_unref0 (_tmp4_); + self->priv->state = SCAN_STATE_START; + _scan_job_unref0 (job); + return; + } + sane_cancel (self->priv->handle); + g_debug ("scanner.vala:1179: sane_cancel ()"); + scanner_do_complete_document (self); + _scan_job_unref0 (job); +} + + +static void scanner_do_read (Scanner* self) { + ScanJob* _tmp0_; + ScanJob* job; + gint n_to_read; + SANE_Int n_read; + guchar* b; + SANE_Int _tmp1_; + SANE_Status _tmp2_; + SANE_Status status; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + gboolean full_read; + gboolean _tmp8_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data)); + job = _tmp0_; + n_to_read = self->priv->buffer_length1 - self->priv->n_used; + b = (guchar*) self->priv->buffer; + _tmp2_ = sane_read (self->priv->handle, (guint8*) (b + self->priv->n_used), (SANE_Int) n_to_read, &_tmp1_); + n_read = _tmp1_; + status = _tmp2_; + _tmp3_ = sane_status_to_string (status); + _tmp4_ = _tmp3_; + g_debug ("scanner.vala:1194: sane_read (%d) -> (%s, %d)", n_to_read, _tmp4_, (gint) n_read); + _g_free0 (_tmp4_); + if (status == SANE_STATUS_EOF) { + gboolean _tmp5_ = FALSE; + if (self->priv->parameters.lines > 0) { + _tmp5_ = self->priv->line_count != self->priv->parameters.lines; + } else { + _tmp5_ = FALSE; + } + if (_tmp5_) { + g_warning ("scanner.vala:1200: Scan completed with %d lines, expected %d lines", self->priv->parameters.lines, self->priv->parameters.lines); + } + if (self->priv->n_used > 0) { + g_warning ("scanner.vala:1202: Scan complete with %d bytes of unused data", self->priv->n_used); + } + scanner_do_complete_page (self); + _scan_job_unref0 (job); + return; + } + if (status != SANE_STATUS_GOOD) { + const gchar* _tmp6_ = NULL; + const gchar* _tmp7_ = NULL; + _tmp6_ = sane_strstatus (status); + g_warning ("scanner.vala:1210: Unable to read frame from device: %s", _tmp6_); + _tmp7_ = _ ("Error communicating with scanner"); + scanner_fail_scan (self, (gint) status, _tmp7_); + _scan_job_unref0 (job); + return; + } + full_read = FALSE; + if (self->priv->n_used == 0) { + _tmp8_ = ((gint) n_read) == self->priv->buffer_length1; + } else { + _tmp8_ = FALSE; + } + if (_tmp8_) { + full_read = TRUE; + } + self->priv->n_used = self->priv->n_used + n_read; + if (self->priv->n_used >= self->priv->parameters.bytes_per_line) { + ScanLine* _tmp9_ = NULL; + ScanLine* line; + guchar* _tmp10_; + gint _tmp11_; + gint buffer_size; + guchar* _tmp12_ = NULL; + gint n_remaining; + gboolean _tmp14_ = FALSE; + gboolean _tmp15_ = FALSE; + gboolean _tmp16_ = FALSE; + NotifyGotLine* _tmp19_ = NULL; + NotifyGotLine* _tmp20_; + _tmp9_ = scan_line_new (); + line = _tmp9_; + switch (self->priv->parameters.format) { + case SANE_FRAME_GRAY: + { + line->channel = 0; + break; + } + case SANE_FRAME_RGB: + { + line->channel = -1; + break; + } + case SANE_FRAME_RED: + { + line->channel = 0; + break; + } + case SANE_FRAME_GREEN: + { + line->channel = 1; + break; + } + case SANE_FRAME_BLUE: + { + line->channel = 2; + break; + } + default: + break; + } + line->width = self->priv->parameters.pixels_per_line; + line->depth = self->priv->parameters.depth; + _tmp10_ = self->priv->buffer; + _tmp11_ = self->priv->buffer_length1; + self->priv->buffer = NULL; + line->data = (g_free (line->data), NULL); + line->data = _tmp10_; + line->data_length1 = _tmp11_; + line->data_length = self->priv->parameters.bytes_per_line; + line->number = self->priv->line_count; + line->n_lines = self->priv->n_used / line->data_length; + self->priv->line_count = self->priv->line_count + line->n_lines; + buffer_size = self->priv->buffer_length1; + if (full_read) { + buffer_size = buffer_size + self->priv->parameters.bytes_per_line; + } + _tmp12_ = g_new0 (guchar, buffer_size); + self->priv->buffer = (g_free (self->priv->buffer), NULL); + self->priv->buffer = _tmp12_; + self->priv->buffer_length1 = buffer_size; + self->priv->_buffer_size_ = self->priv->buffer_length1; + n_remaining = self->priv->n_used - (line->n_lines * line->data_length); + self->priv->n_used = 0; + { + gint i; + i = 0; + { + gboolean _tmp13_; + _tmp13_ = TRUE; + while (TRUE) { + if (!_tmp13_) { + i++; + } + _tmp13_ = FALSE; + if (!(i < n_remaining)) { + break; + } + self->priv->buffer[i] = line->data[i + (line->n_lines * line->data_length)]; + self->priv->n_used++; + } + } + } + if (self->priv->parameters.depth == 8) { + _tmp16_ = self->priv->parameters.format == SANE_FRAME_GRAY; + } else { + _tmp16_ = FALSE; + } + if (_tmp16_) { + _tmp15_ = job->depth == 2; + } else { + _tmp15_ = FALSE; + } + if (_tmp15_) { + _tmp14_ = job->scan_mode == SCAN_MODE_GRAY; + } else { + _tmp14_ = FALSE; + } + if (_tmp14_) { + guchar block; + gint write_offset; + gint block_shift; + block = (guchar) 0; + write_offset = 0; + block_shift = 6; + { + gint i; + i = 0; + { + gboolean _tmp17_; + _tmp17_ = TRUE; + while (TRUE) { + gint offset; + if (!_tmp17_) { + i++; + } + _tmp17_ = FALSE; + if (!(i < line->n_lines)) { + break; + } + offset = i * line->data_length; + { + gint x; + x = 0; + { + gboolean _tmp18_; + _tmp18_ = TRUE; + while (TRUE) { + guchar p; + guchar sample = '\0'; + if (!_tmp18_) { + x++; + } + _tmp18_ = FALSE; + if (!(x < line->width)) { + break; + } + p = line->data[offset + x]; + if (((gint) p) >= 192) { + sample = (guchar) 3; + } else { + if (((gint) p) >= 128) { + sample = (guchar) 2; + } else { + if (((gint) p) >= 64) { + sample = (guchar) 1; + } else { + sample = (guchar) 0; + } + } + } + block = block | (sample << block_shift); + if (block_shift == 0) { + line->data[write_offset] = block; + write_offset++; + block = (guchar) 0; + block_shift = 6; + } else { + block_shift = block_shift - 2; + } + } + } + } + if (block_shift != 6) { + line->data[write_offset] = block; + write_offset++; + block = (guchar) 0; + block_shift = 6; + } + } + } + } + line->data_length = ((line->width * 2) + 7) / 8; + } + _tmp19_ = notify_got_line_new (line); + _tmp20_ = _tmp19_; + scanner_notify (self, (Notify*) _tmp20_); + _notify_unref0 (_tmp20_); + _scan_line_unref0 (line); + } + _scan_job_unref0 (job); +} + + +static void _scanner_authorization_cb_sane_authcallback (const gchar* resource, gchar* username, gchar* password) { + scanner_authorization_cb (resource, username, -1, password, -1); +} + + +static void* scanner_scan_thread (Scanner* self) { + void* result = NULL; + SANE_Int version_code; + SANE_Int _tmp0_; + SANE_Status _tmp1_; + SANE_Status status; + gchar* _tmp2_ = NULL; + gchar* _tmp3_; + gint _tmp5_; + gint _tmp6_; + gint _tmp7_; + g_return_val_if_fail (self != NULL, NULL); + self->priv->state = SCAN_STATE_IDLE; + _tmp1_ = sane_init (&_tmp0_, _scanner_authorization_cb_sane_authcallback); + version_code = _tmp0_; + status = _tmp1_; + _tmp2_ = sane_status_to_string (status); + _tmp3_ = _tmp2_; + g_debug ("scanner.vala:1327: sane_init () -> %s", _tmp3_); + _g_free0 (_tmp3_); + if (status != SANE_STATUS_GOOD) { + const gchar* _tmp4_ = NULL; + _tmp4_ = sane_strstatus (status); + g_warning ("scanner.vala:1330: Unable to initialize SANE backend: %s", _tmp4_); + result = NULL; + return result; + } + _tmp5_ = SANE_VERSION_MAJOR (version_code); + _tmp6_ = SANE_VERSION_MINOR (version_code); + _tmp7_ = SANE_VERSION_BUILD (version_code); + g_debug ("scanner.vala:1333: SANE version %d.%d.%d", _tmp5_, _tmp6_, _tmp7_); + scanner_redetect (self); + while (TRUE) { + gboolean _tmp8_; + _tmp8_ = scanner_handle_requests (self); + if (!_tmp8_) { + break; + } + switch (self->priv->state) { + case SCAN_STATE_IDLE: + { + if (self->priv->job_queue != NULL) { + scanner_set_scanning (self, TRUE); + self->priv->state = SCAN_STATE_OPEN; + } + break; + } + case SCAN_STATE_REDETECT: + { + scanner_do_redetect (self); + break; + } + case SCAN_STATE_OPEN: + { + scanner_do_open (self); + break; + } + case SCAN_STATE_GET_OPTION: + { + scanner_do_get_option (self); + break; + } + case SCAN_STATE_START: + { + scanner_do_start (self); + break; + } + case SCAN_STATE_GET_PARAMETERS: + { + scanner_do_get_parameters (self); + break; + } + case SCAN_STATE_READ: + { + scanner_do_read (self); + break; + } + default: + break; + } + } + result = NULL; + return result; +} + + +static gpointer _scanner_scan_thread_gthread_func (gpointer self) { + gpointer result; + result = scanner_scan_thread (self); + return result; +} + + +void scanner_start (Scanner* self) { + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + { + GThread* _tmp0_ = NULL; + GThread* _tmp1_; + _tmp0_ = g_thread_create (_scanner_scan_thread_gthread_func, self, TRUE, &_inner_error_); + _tmp1_ = _tmp0_; + if (_inner_error_ != NULL) { + goto __catch9_g_error; + } + self->priv->thread = _tmp1_; + } + goto __finally9; + __catch9_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_critical ("scanner.vala:1384: Unable to create thread: %s", e->message); + _g_error_free0 (e); + } + __finally9: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } +} + + +void scanner_redetect (Scanner* self) { + RequestRedetect* _tmp0_ = NULL; + g_return_if_fail (self != NULL); + if (self->priv->need_redetect) { + return; + } + self->priv->need_redetect = TRUE; + g_debug ("scanner.vala:1394: Requesting redetection of scan devices"); + _tmp0_ = request_redetect_new (); + g_async_queue_push (self->priv->request_queue, (Request*) _tmp0_); +} + + +gboolean scanner_is_scanning (Scanner* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->scanning; + return result; +} + + +static gchar* scanner_get_scan_mode_string (Scanner* self, ScanMode mode) { + gchar* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + switch (mode) { + case SCAN_MODE_DEFAULT: + { + gchar* _tmp0_; + _tmp0_ = g_strdup ("ScanMode.DEFAULT"); + result = _tmp0_; + return result; + } + case SCAN_MODE_COLOR: + { + gchar* _tmp1_; + _tmp1_ = g_strdup ("ScanMode.COLOR"); + result = _tmp1_; + return result; + } + case SCAN_MODE_GRAY: + { + gchar* _tmp2_; + _tmp2_ = g_strdup ("ScanMode.GRAY"); + result = _tmp2_; + return result; + } + case SCAN_MODE_LINEART: + { + gchar* _tmp3_; + _tmp3_ = g_strdup ("ScanMode.LINEART"); + result = _tmp3_; + return result; + } + default: + { + gchar* _tmp4_ = NULL; + _tmp4_ = g_strdup_printf ("%d", (gint) mode); + result = _tmp4_; + return result; + } + } +} + + +static gchar* scanner_get_scan_type_string (Scanner* self, ScanType type) { + gchar* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + switch (type) { + case SCAN_TYPE_SINGLE: + { + gchar* _tmp0_; + _tmp0_ = g_strdup ("ScanType.SINGLE"); + result = _tmp0_; + return result; + } + case SCAN_TYPE_ADF_FRONT: + { + gchar* _tmp1_; + _tmp1_ = g_strdup ("ScanType.ADF_FRONT"); + result = _tmp1_; + return result; + } + case SCAN_TYPE_ADF_BACK: + { + gchar* _tmp2_; + _tmp2_ = g_strdup ("ScanType.ADF_BACK"); + result = _tmp2_; + return result; + } + case SCAN_TYPE_ADF_BOTH: + { + gchar* _tmp3_; + _tmp3_ = g_strdup ("ScanType.ADF_BOTH"); + result = _tmp3_; + return result; + } + default: + { + gchar* _tmp4_ = NULL; + _tmp4_ = g_strdup_printf ("%d", (gint) type); + result = _tmp4_; + return result; + } + } +} + + +void scanner_scan (Scanner* self, const gchar* device, ScanOptions* options) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + RequestStartScan* _tmp5_ = NULL; + RequestStartScan* request; + ScanJob* _tmp6_ = NULL; + gchar* _tmp7_; + Request* _tmp8_; + g_return_if_fail (self != NULL); + g_return_if_fail (options != NULL); + if (device != NULL) { + _tmp0_ = device; + } else { + _tmp0_ = "(null)"; + } + _tmp1_ = scanner_get_scan_mode_string (self, options->scan_mode); + _tmp2_ = _tmp1_; + _tmp3_ = scanner_get_scan_type_string (self, options->type); + _tmp4_ = _tmp3_; + g_debug ("scanner.vala:1440: Scanner.scan (\"%s\", dpi=%d, scan_mode=%s, depth=%" \ +"d, type=%s, paper_width=%d, paper_height=%d)", _tmp0_, options->dpi, _tmp2_, options->depth, _tmp4_, options->paper_width, options->paper_height); + _g_free0 (_tmp4_); + _g_free0 (_tmp2_); + _tmp5_ = request_start_scan_new (); + request = _tmp5_; + _tmp6_ = scan_job_new (); + _scan_job_unref0 (request->job); + request->job = _tmp6_; + _tmp7_ = g_strdup (device); + _g_free0 (request->job->device); + request->job->device = _tmp7_; + request->job->dpi = (gdouble) options->dpi; + request->job->scan_mode = options->scan_mode; + request->job->depth = options->depth; + request->job->type = options->type; + request->job->page_width = options->paper_width; + request->job->page_height = options->paper_height; + _tmp8_ = _request_ref0 ((Request*) request); + g_async_queue_push (self->priv->request_queue, _tmp8_); + _request_unref0 (request); +} + + +void scanner_cancel (Scanner* self) { + RequestCancel* _tmp0_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = request_cancel_new (); + g_async_queue_push (self->priv->request_queue, (Request*) _tmp0_); +} + + +void scanner_free (Scanner* self) { + RequestQuit* _tmp0_ = NULL; + g_return_if_fail (self != NULL); + g_debug ("scanner.vala:1462: Stopping scan thread"); + _tmp0_ = request_quit_new (); + g_async_queue_push (self->priv->request_queue, (Request*) _tmp0_); + if (self->priv->thread != NULL) { + g_thread_join (self->priv->thread); + } + sane_exit (); + g_debug ("scanner.vala:1470: sane_exit ()"); +} + + +static void g_cclosure_user_marshal_VOID__SCAN_PAGE_INFO (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__SCAN_PAGE_INFO) (gpointer data1, gpointer arg_1, gpointer data2); + register GMarshalFunc_VOID__SCAN_PAGE_INFO callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 2); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__SCAN_PAGE_INFO) (marshal_data ? marshal_data : cc->callback); + callback (data1, value_get_scan_page_info (param_values + 1), data2); +} + + +static void g_cclosure_user_marshal_VOID__SCAN_LINE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__SCAN_LINE) (gpointer data1, gpointer arg_1, gpointer data2); + register GMarshalFunc_VOID__SCAN_LINE callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 2); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__SCAN_LINE) (marshal_data ? marshal_data : cc->callback); + callback (data1, value_get_scan_line (param_values + 1), data2); +} + + +static void g_cclosure_user_marshal_VOID__INT_STRING (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__INT_STRING) (gpointer data1, gint arg_1, const char* arg_2, gpointer data2); + register GMarshalFunc_VOID__INT_STRING callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 3); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__INT_STRING) (marshal_data ? marshal_data : cc->callback); + callback (data1, g_value_get_int (param_values + 1), g_value_get_string (param_values + 2), data2); +} + + +static void value_scanner_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_scanner_free_value (GValue* value) { + if (value->data[0].v_pointer) { + scanner_unref (value->data[0].v_pointer); + } +} + + +static void value_scanner_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = scanner_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_scanner_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_scanner_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Scanner* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = scanner_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_scanner_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Scanner** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = scanner_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_scanner (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecScanner* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCANNER), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_scanner (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCANNER), NULL); + return value->data[0].v_pointer; +} + + +void value_set_scanner (GValue* value, gpointer v_object) { + Scanner* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCANNER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCANNER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + scanner_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scanner_unref (old); + } +} + + +void value_take_scanner (GValue* value, gpointer v_object) { + Scanner* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCANNER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCANNER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + scanner_unref (old); + } +} + + +static void scanner_class_init (ScannerClass * klass) { + scanner_parent_class = g_type_class_peek_parent (klass); + SCANNER_CLASS (klass)->finalize = scanner_finalize; + g_type_class_add_private (klass, sizeof (ScannerPrivate)); + g_signal_new ("update_devices", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + g_signal_new ("request_authorization", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + g_signal_new ("expect_page", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("got_page_info", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__SCAN_PAGE_INFO, G_TYPE_NONE, 1, TYPE_SCAN_PAGE_INFO); + g_signal_new ("got_line", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__SCAN_LINE, G_TYPE_NONE, 1, TYPE_SCAN_LINE); + g_signal_new ("scan_failed", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__INT_STRING, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + g_signal_new ("page_done", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("document_done", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("scanning_changed", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +} + + +static void scanner_instance_init (Scanner * self) { + self->priv = SCANNER_GET_PRIVATE (self); + self->ref_count = 1; +} + + +static void scanner_finalize (Scanner* obj) { + Scanner * self; + self = SCANNER (obj); + _g_async_queue_unref0 (self->priv->request_queue); + _g_async_queue_unref0 (self->priv->notify_queue); + _g_async_queue_unref0 (self->priv->authorize_queue); + _g_free0 (self->priv->default_device); + __g_list_free__scan_job_unref0_0 (self->priv->job_queue); + _g_free0 (self->priv->current_device); + self->priv->buffer = (g_free (self->priv->buffer), NULL); +} + + +GType scanner_get_type (void) { + static volatile gsize scanner_type_id__volatile = 0; + if (g_once_init_enter (&scanner_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_scanner_init, value_scanner_free_value, value_scanner_copy_value, value_scanner_peek_pointer, "p", value_scanner_collect_value, "p", value_scanner_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ScannerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scanner_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Scanner), 0, (GInstanceInitFunc) scanner_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType scanner_type_id; + scanner_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Scanner", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&scanner_type_id__volatile, scanner_type_id); + } + return scanner_type_id__volatile; +} + + +gpointer scanner_ref (gpointer instance) { + Scanner* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void scanner_unref (gpointer instance) { + Scanner* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SCANNER_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); +} + + + diff --git a/src/scanner.h b/src/scanner.h deleted file mode 100644 index 72a4ffd..0000000 --- a/src/scanner.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2009 Canonical Ltd. - * Author: Robert Ancell <robert.ancell@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. See http://www.gnu.org/copyleft/gpl.html the full text of the - * license. - */ - -#ifndef _SCANNER_H_ -#define _SCANNER_H_ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define SCANNER_TYPE (scanner_get_type ()) -#define SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SCANNER_TYPE, Scanner)) - - -typedef struct -{ - gchar *name, *label; -} ScanDevice; - -typedef struct -{ - /* Width, height in pixels */ - gint width, height; - - /* Bit depth */ - gint depth; - - /* Number of colour channels */ - gint n_channels; - - /* Resolution */ - gdouble dpi; - - /* The device this page came from */ - gchar *device; -} ScanPageInfo; - -typedef struct -{ - /* Line number */ - gint number; - - /* Number of lines in this packet */ - gint n_lines; - - /* Width in pixels and format */ - gint width, depth; - - /* Channel for this line or -1 for all channels */ - gint channel; - - /* Raw line data */ - guchar *data; - gsize data_length; -} ScanLine; - -typedef enum -{ - SCAN_MODE_DEFAULT, - SCAN_MODE_COLOR, - SCAN_MODE_GRAY, - SCAN_MODE_LINEART -} ScanMode; - -typedef enum -{ - SCAN_SINGLE, - SCAN_ADF_FRONT, - SCAN_ADF_BACK, - SCAN_ADF_BOTH -} ScanType; - -typedef struct -{ - gint dpi; - ScanMode scan_mode; - gint depth; - ScanType type; - gint paper_width, paper_height; -} ScanOptions; - -typedef struct ScannerPrivate ScannerPrivate; - -typedef struct -{ - GObject parent_instance; - ScannerPrivate *priv; -} Scanner; - -typedef struct -{ - GObjectClass parent_class; - - void (*update_devices) (Scanner *scanner, GList *devices); - void (*authorize) (Scanner *scanner, const gchar *resource); - void (*expect_page) (Scanner *scanner); - void (*got_page_info) (Scanner *scanner, ScanPageInfo *info); - void (*got_line) (Scanner *scanner, ScanLine *line); - void (*scan_failed) (Scanner *scanner, GError *error); - void (*page_done) (Scanner *scanner); - void (*document_done) (Scanner *scanner); - void (*scanning_changed) (Scanner *scanner); -} ScannerClass; - - -GType scanner_get_type (void); - -Scanner *scanner_new (void); - -void scanner_start (Scanner *scanner); - -void scanner_authorize (Scanner *scanner, const gchar *username, const gchar *password); - -void scanner_redetect (Scanner *scanner); - -gboolean scanner_is_scanning (Scanner *scanner); - -void scanner_scan (Scanner *scanner, const char *device, ScanOptions *options); - -void scanner_cancel (Scanner *scanner); - -void scanner_free (Scanner *scanner); - -#endif /* _SCANNER_H_ */ diff --git a/src/scanner.vala b/src/scanner.vala new file mode 100644 index 0000000..02aa69d --- /dev/null +++ b/src/scanner.vala @@ -0,0 +1,1472 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +/* TODO: Could indicate the start of the next page immediately after the last page is received (i.e. before the sane_cancel()) */ + +public class ScanDevice +{ + public string name; + public string label; +} + +public class ScanPageInfo +{ + /* Width, height in pixels */ + public int width; + public int height; + + /* Bit depth */ + public int depth; + + /* Number of colour channels */ + public int n_channels; + + /* Resolution */ + public double dpi; + + /* The device this page came from */ + public string device; +} + +public class ScanLine +{ + /* Line number */ + public int number; + + /* Number of lines in this packet */ + public int n_lines; + + /* Width in pixels and format */ + public int width; + public int depth; + + /* Channel for this line or -1 for all channels */ + public int channel; + + /* Raw line data */ + public uchar[] data; + public int data_length; +} + +public enum ScanMode +{ + DEFAULT, + COLOR, + GRAY, + LINEART +} + +public enum ScanType +{ + SINGLE, + ADF_FRONT, + ADF_BACK, + ADF_BOTH +} + +public class ScanOptions +{ + public int dpi; + public ScanMode scan_mode; + public int depth; + public ScanType type; + public int paper_width; + public int paper_height; +} + +private class ScanJob +{ + public string device; + public double dpi; + public ScanMode scan_mode; + public int depth; + public ScanType type; + public int page_width; + public int page_height; +} + +private class Request {} + +private class RequestRedetect : Request {} + +private class RequestCancel : Request {} + +private class RequestStartScan : Request +{ + public ScanJob job; +} + +private class RequestQuit : Request {} + +private class Credentials +{ + public string username; + public string password; +} + +private enum ScanState +{ + IDLE = 0, + REDETECT, + OPEN, + GET_OPTION, + START, + GET_PARAMETERS, + READ +} + +private class Notify +{ + public virtual void run (Scanner scanner) {} +} + +private class NotifyScanningChanged : Notify +{ + public override void run (Scanner scanner) { scanner.scanning_changed (); } +} + +private class NotifyUpdateDevices : Notify +{ + public NotifyUpdateDevices (owned List<ScanDevice> devices) { this.devices = (owned) devices; } + private List<ScanDevice> devices; + public override void run (Scanner scanner) { scanner.update_devices (devices); } +} + +private class NotifyRequestAuthorization : Notify +{ + public NotifyRequestAuthorization (string resource) { this.resource = resource; } + private string resource; + public override void run (Scanner scanner) { scanner.request_authorization (resource); } +} + +private class NotifyScanFailed : Notify +{ + public NotifyScanFailed (int error_code, string error_string) { this.error_code = error_code; this.error_string = error_string; } + private int error_code; + private string error_string; + public override void run (Scanner scanner) { scanner.scan_failed (error_code, error_string); } +} + +private class NotifyDocumentDone : Notify +{ + public override void run (Scanner scanner) { scanner.document_done (); } +} + +private class NotifyExpectPage : Notify +{ + public override void run (Scanner scanner) { scanner.expect_page (); } +} + +private class NotifyGotPageInfo : Notify +{ + public NotifyGotPageInfo (ScanPageInfo info) { this.info = info; } + private ScanPageInfo info; + public override void run (Scanner scanner) { scanner.got_page_info (info); } +} + +private class NotifyPageDone : Notify +{ + public override void run (Scanner scanner) { scanner.page_done (); } +} + +private class NotifyGotLine : Notify +{ + public NotifyGotLine (ScanLine line) { this.line = line; } + private ScanLine line; + public override void run (Scanner scanner) + { + scanner.got_line (line); + } +} + +public class Scanner +{ + /* Singleton object */ + private static Scanner scanner_object = null; + + /* Thread communicating with SANE */ + private unowned Thread<void*> thread; + + /* Queue of requests from main thread */ + private AsyncQueue<Request> request_queue; + + /* Queue of events to notify in main queue */ + private AsyncQueue<Notify> notify_queue; + + /* Queue of responses to authorization requests */ + private AsyncQueue<Credentials> authorize_queue; + + private string? default_device; + + private ScanState state; + private bool need_redetect; + + private List<ScanJob> job_queue; + + /* Handle to SANE device */ + private Sane.Handle handle; + private bool have_handle; + private string? current_device; + + private Sane.Parameters parameters; + + /* Last option read */ + private Sane.Int option_index; + + /* Option index for scan area */ + private Sane.Int br_x_option_index; + private Sane.Int br_y_option_index; + + /* Buffer for received line */ + private uchar[] buffer; + private int n_used; + + //private int bytes_remaining; + private int line_count; + private int pass_number; + private int page_number; + private int notified_page; + + private bool scanning; + + public signal void update_devices (List<ScanDevice> devices); + public signal void request_authorization (string resource); + public signal void expect_page (); + public signal void got_page_info (ScanPageInfo info); + public signal void got_line (ScanLine line); + public signal void scan_failed (int error_code, string error_string); + public signal void page_done (); + public signal void document_done (); + public signal void scanning_changed (); + + private Scanner () + { + request_queue = new AsyncQueue<Request> (); + notify_queue = new AsyncQueue<Notify> (); + authorize_queue = new AsyncQueue<Credentials> (); + } + + public static Scanner get_instance () + { + if (scanner_object == null) + scanner_object = new Scanner (); + return scanner_object; + } + + private bool notify_idle_cb () + { + var notification = notify_queue.pop (); + notification.run (this); + return false; + } + + private void notify (Notify notification) + { + notify_queue.push (notification); + Idle.add (notify_idle_cb); + } + + private void set_scanning (bool is_scanning) + { + if ((scanning && !is_scanning) || (!scanning && is_scanning)) + { + scanning = is_scanning; + scanning_changed (); + notify (new NotifyScanningChanged ()); + } + } + + private static int get_device_weight (string device) + { + /* NOTE: This is using trends in the naming of SANE devices, SANE should be able to provide this information better */ + + /* Use webcams as a last resort */ + if (device.has_prefix ("vfl:")) + return 2; + + /* Use locally connected devices first */ + if (device.contains ("usb")) + return 0; + + return 1; + } + + private static int compare_devices (ScanDevice device1, ScanDevice device2) + { + /* TODO: Should do some fuzzy matching on the last selected device and set that to the default */ + + var weight1 = get_device_weight (device1.name); + var weight2 = get_device_weight (device2.name); + if (weight1 != weight2) + return weight1 - weight2; + + return strcmp (device1.label, device2.label); + } + + private void do_redetect () + { + unowned Sane.Device[] device_list = null; + var status = Sane.get_devices (out device_list, false); + debug ("sane_get_devices () -> %s", Sane.status_to_string (status)); + if (status != Sane.Status.GOOD) + { + warning ("Unable to get SANE devices: %s", Sane.strstatus(status)); + need_redetect = false; + state = ScanState.IDLE; + return; + } + + List<ScanDevice> devices = null; + for (var i = 0; device_list[i] != null; i++) + { + debug ("Device: name=\"%s\" vendor=\"%s\" model=\"%s\" type=\"%s\"", + device_list[i].name, device_list[i].vendor, device_list[i].model, device_list[i].type); + + var scan_device = new ScanDevice (); + scan_device.name = device_list[i].name; + + /* Abbreviate HP as it is a long string and does not match what is on the physical scanner */ + var vendor = device_list[i].vendor; + if (vendor == "Hewlett-Packard") + vendor = "HP"; + + scan_device.label = "%s %s".printf (vendor, device_list[i].model); + /* Replace underscores in name */ + scan_device.label.replace ("_", " "); + + devices.append (scan_device); + } + + /* Sort devices by priority */ + devices.sort (compare_devices); + + need_redetect = false; + state = ScanState.IDLE; + + if (devices != null) + { + var device = devices.nth_data (0); + default_device = device.name; + } + else + default_device = null; + + notify (new NotifyUpdateDevices ((owned) devices)); + } + + private bool set_default_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index) + { + /* Check if supports automatic option */ + if ((option.cap & Sane.Capability.AUTOMATIC) == 0) + return false; + + var status = Sane.control_option (handle, option_index, Sane.Action.SET_AUTO, null, null); + debug ("sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s", option_index, Sane.status_to_string (status)); + if (status != Sane.Status.GOOD) + warning ("Error setting default option %s: %s", option.name, Sane.strstatus(status)); + + return status == Sane.Status.GOOD; + } + + private void set_bool_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, bool value, out bool result) + { + return_if_fail (option.type == Sane.ValueType.BOOL); + + Sane.Bool v = (Sane.Bool) value; + var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v, null); + result = (bool) v; + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s) -> (%s, %s)", option_index, value ? "SANE_TRUE" : "SANE_FALSE", Sane.status_to_string (status), result ? "SANE_TRUE" : "SANE_FALSE"); + } + + private void set_int_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, int value, out int result) + { + return_if_fail (option.type == Sane.ValueType.INT); + + Sane.Int v = (Sane.Int) value; + if (option.constraint_type == Sane.ConstraintType.RANGE) + { + if (option.constraint.range.quant != 0) + v *= option.constraint.range.quant; + if (v < option.constraint.range.min) + v = option.constraint.range.min; + if (v > option.constraint.range.max) + v = option.constraint.range.max; + } + else if (option.constraint_type == Sane.ConstraintType.WORD_LIST) + { + int distance = int.MAX, nearest = 0; + + /* Find nearest value to requested */ + for (var i = 0; i < option.constraint.word_list[0]; i++) + { + var x = (int) option.constraint.word_list[i+1]; + var d = (x - v).abs (); + if (d < distance) + { + distance = d; + nearest = x; + } + } + v = (Sane.Int) nearest; + } + + var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v, null); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %d) -> (%s, %d)", option_index, value, Sane.status_to_string (status), v); + result = v; + } + + private void set_fixed_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, double value, out double result) + { + double v = value; + Sane.Fixed v_fixed; + + return_if_fail (option.type == Sane.ValueType.FIXED); + + if (option.constraint_type == Sane.ConstraintType.RANGE) + { + double min = Sane.UNFIX (option.constraint.range.min); + double max = Sane.UNFIX (option.constraint.range.max); + + if (v < min) + v = min; + if (v > max) + v = max; + } + else if (option.constraint_type == Sane.ConstraintType.WORD_LIST) + { + double distance = double.MAX, nearest = 0.0; + + /* Find nearest value to requested */ + for (var i = 0; i < option.constraint.word_list[0]; i++) + { + double x = Sane.UNFIX (option.constraint.word_list[i+1]); + if (Math.fabs (x - v) < distance) + { + distance = Math.fabs (x - v); + nearest = x; + } + } + v = nearest; + } + + v_fixed = Sane.FIX (v); + var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v_fixed, null); + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %f) -> (%s, %f)", option_index, value, Sane.status_to_string (status), Sane.UNFIX (v_fixed)); + + result = Sane.UNFIX (v_fixed); + } + + private bool set_string_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, string value, out string result) + { + return_val_if_fail (option.type == Sane.ValueType.STRING, false); + + var s = new char[option.size]; + var i = 0; + for (; i < (option.size - 1) && value[i] != '\0'; i++) + s[i] = value[i]; + s[i] = '\0'; + var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, s, null); + result = (string) s; + debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, \"%s\") -> (%s, \"%s\")", option_index, value, Sane.status_to_string (status), result); + + return status == Sane.Status.GOOD; + } + + private bool set_constrained_string_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, string[] values, out string result) + { + return_val_if_fail (option.type == Sane.ValueType.STRING, false); + return_val_if_fail (option.constraint_type == Sane.ConstraintType.STRING_LIST, false); + + for (var i = 0; values[i] != null; i++) + { + var j = 0; + for (; option.constraint.string_list[j] != null; j++) + { + if (values[i] == option.constraint.string_list[j]) + break; + } + + if (option.constraint.string_list[j] != null) + return set_string_option (handle, option, option_index, values[i], out result); + } + + return false; + } + + private void log_option (Sane.Int index, Sane.OptionDescriptor option) + { + var s = "Option %d:".printf (index); + + if (option.name != "") + s += " name='%s'".printf (option.name); + + if (option.title != "") + s += " title='%s'".printf (option.title); + + switch (option.type) + { + case Sane.ValueType.BOOL: + s += " type=bool"; + break; + case Sane.ValueType.INT: + s += " type=int"; + break; + case Sane.ValueType.FIXED: + s += " type=fixed"; + break; + case Sane.ValueType.STRING: + s += " type=string"; + break; + case Sane.ValueType.BUTTON: + s += " type=button"; + break; + case Sane.ValueType.GROUP: + s += " type=group"; + break; + default: + s += " type=%d".printf (option.type); + break; + } + + s += " size=%d".printf (option.size); + + switch (option.unit) + { + case Sane.Unit.NONE: + break; + case Sane.Unit.PIXEL: + s += " unit=pixels"; + break; + case Sane.Unit.BIT: + s += " unit=bits"; + break; + case Sane.Unit.MM: + s += " unit=mm"; + break; + case Sane.Unit.DPI: + s += " unit=dpi"; + break; + case Sane.Unit.PERCENT: + s += " unit=percent"; + break; + case Sane.Unit.MICROSECOND: + s += " unit=microseconds"; + break; + default: + s += " unit=%d".printf (option.unit); + break; + } + + switch (option.constraint_type) + { + case Sane.ConstraintType.RANGE: + if (option.type == Sane.ValueType.FIXED) + s += " min=%f, max=%f, quant=%d".printf (Sane.UNFIX (option.constraint.range.min), Sane.UNFIX (option.constraint.range.max), option.constraint.range.quant); + else + s += " min=%d, max=%d, quant=%d".printf (option.constraint.range.min, option.constraint.range.max, option.constraint.range.quant); + break; + case Sane.ConstraintType.WORD_LIST: + s += " values=["; + for (var i = 0; i < option.constraint.word_list[0]; i++) + { + if (i != 0) + s += ", "; + if (option.type == Sane.ValueType.INT) + s += "%d".printf (option.constraint.word_list[i+1]); + else + s += "%f".printf (Sane.UNFIX (option.constraint.word_list[i+1])); + } + s += "]"; + break; + case Sane.ConstraintType.STRING_LIST: + s += " values=["; + for (var i = 0; option.constraint.string_list[i] != null; i++) + { + if (i != 0) + s += ", "; + s += "\"%s\"".printf (option.constraint.string_list[i]); + } + s += "]"; + break; + default: + break; + } + + var cap = option.cap; + if (cap != 0) + { + s += " cap="; + if ((cap & Sane.Capability.SOFT_SELECT) != 0) + { + if (s != "") + s += ","; + s += "soft-select"; + cap &= ~Sane.Capability.SOFT_SELECT; + } + if ((cap & Sane.Capability.HARD_SELECT) != 0) + { + if (s != "") + s += ","; + s += "hard-select"; + cap &= ~Sane.Capability.HARD_SELECT; + } + if ((cap & Sane.Capability.SOFT_DETECT) != 0) + { + if (s != "") + s += ","; + s += "soft-detect"; + cap &= ~Sane.Capability.SOFT_DETECT; + } + if ((cap & Sane.Capability.EMULATED) != 0) + { + if (s != "") + s += ","; + s += "emulated"; + cap &= ~Sane.Capability.EMULATED; + } + if ((cap & Sane.Capability.AUTOMATIC) != 0) + { + if (s != "") + s += ","; + s += "automatic"; + cap &= ~Sane.Capability.AUTOMATIC; + } + if ((cap & Sane.Capability.INACTIVE) != 0) + { + if (s != "") + s += ","; + s += "inactive"; + cap &= ~Sane.Capability.INACTIVE; + } + if ((cap & Sane.Capability.ADVANCED) != 0) + { + if (s != "") + s += ","; + s += "advanced"; + cap &= ~Sane.Capability.ADVANCED; + } + /* Unknown capabilities */ + if (cap != 0) + { + if (s != "") + s += ","; + s += "%x".printf (cap); + } + } + + debug ("%s", s); + + if (option.desc != null) + debug (" Description: %s", option.desc); + } + + private static void authorization_cb (string resource, char[] username, char[] password) + { + scanner_object.notify (new NotifyRequestAuthorization (resource)); + + var credentials = scanner_object.authorize_queue.pop (); + for (var i = 0; credentials.username[i] != '\0' && i < Sane.MAX_USERNAME_LEN; i++) + username[i] = credentials.username[i]; + for (var i = 0; credentials.password[i] != '\0' && i < Sane.MAX_PASSWORD_LEN; i++) + password[i] = credentials.password[i]; + } + + public void authorize (string username, string password) + { + var credentials = new Credentials (); + credentials.username = username; + credentials.password = password; + authorize_queue.push (credentials); + } + + private void close_device () + { + if (have_handle) + { + Sane.cancel (handle); + debug ("sane_cancel ()"); + + Sane.close (handle); + debug ("sane_close ()"); + have_handle = false; + } + + buffer = null; + job_queue = null; + + set_scanning (false); + } + + private void fail_scan (int error_code, string error_string) + { + close_device (); + state = ScanState.IDLE; + notify (new NotifyScanFailed (error_code, error_string)); + } + + private bool handle_requests () + { + /* Redetect when idle */ + if (state == ScanState.IDLE && need_redetect) + state = ScanState.REDETECT; + + /* Process all requests */ + int request_count = 0; + while (true) + { + Request request; + if ((state == ScanState.IDLE && request_count == 0) || + request_queue.length () > 0) + request = request_queue.pop (); + else + return true; + + debug ("Processing request"); + request_count++; + + if (request is RequestStartScan) + { + var r = (RequestStartScan) request; + job_queue.append (r.job); + } + else if (request is RequestCancel) + { + fail_scan (Sane.Status.CANCELLED, "Scan cancelled - do not report this error"); + } + else if (request is RequestQuit) + { + close_device (); + return false; + } + } + } + + private void do_open () + { + var job = (ScanJob) job_queue.data; + + line_count = 0; + pass_number = 0; + page_number = 0; + notified_page = -1; + option_index = 0; + br_x_option_index = 0; + br_y_option_index = 0; + + if (job.device == null && default_device != null) + job.device = default_device; + + if (job.device == null) + { + warning ("No scan device available"); + fail_scan (0, + /* Error displayed when no scanners to scan with */ + _("No scanners available. Please connect a scanner.")); + return; + } + + /* See if we can use the already open device */ + if (have_handle) + { + if (current_device == job.device) + { + state = ScanState.GET_OPTION; + return; + } + + Sane.close (handle); + debug ("sane_close ()"); + have_handle = false; + } + + current_device = null; + + have_handle = false; + var status = Sane.open (job.device, out handle); + debug ("sane_open (\"%s\") -> %s", job.device, Sane.status_to_string (status)); + + if (status != Sane.Status.GOOD) + { + warning ("Unable to get open device: %s", Sane.strstatus (status)); + fail_scan (status, + /* Error displayed when cannot connect to scanner */ + _("Unable to connect to scanner")); + return; + } + have_handle = true; + + current_device = job.device; + state = ScanState.GET_OPTION; + } + + private void do_get_option () + { + var job = (ScanJob) job_queue.data; + + var option = Sane.get_option_descriptor (handle, option_index); + debug ("sane_get_option_descriptor (%d)", option_index); + var index = option_index; + option_index++; + + if (option == null) + { + /* Always use maximum scan area - some scanners default to using partial areas. This should be patched in sane-backends */ + if (br_x_option_index != 0) + { + option = Sane.get_option_descriptor (handle, br_x_option_index); + debug ("sane_get_option_descriptor (%d)", br_x_option_index); + if (option.constraint_type == Sane.ConstraintType.RANGE) + { + if (option.type == Sane.ValueType.FIXED) + set_fixed_option (handle, option, br_x_option_index, Sane.UNFIX (option.constraint.range.max), null); + else + set_int_option (handle, option, br_x_option_index, option.constraint.range.max, null); + } + } + if (br_y_option_index != 0) + { + option = Sane.get_option_descriptor (handle, br_y_option_index); + debug ("sane_get_option_descriptor (%d)", br_y_option_index); + if (option.constraint_type == Sane.ConstraintType.RANGE) + { + if (option.type == Sane.ValueType.FIXED) + set_fixed_option (handle, option, br_y_option_index, Sane.UNFIX (option.constraint.range.max), null); + else + set_int_option (handle, option, br_y_option_index, option.constraint.range.max, null); + } + } + + state = ScanState.START; + return; + } + + log_option (index, option); + + /* Ignore groups */ + if (option.type == Sane.ValueType.GROUP) + return; + + /* Option disabled */ + if ((option.cap & Sane.Capability.INACTIVE) != 0) + return; + + /* Some options are unnammed (e.g. Option 0) */ + if (option.name == null) + return; + + if (option.name == Sane.NAME_SCAN_RESOLUTION) + { + if (option.type == Sane.ValueType.FIXED) + set_fixed_option (handle, option, index, job.dpi, out job.dpi); + else + { + int dpi; + set_int_option (handle, option, index, (int) job.dpi, out dpi); + job.dpi = dpi; + } + } + else if (option.name == Sane.NAME_SCAN_SOURCE) + { + string[] flatbed_sources = + { + "Auto", + Sane.I18N ("Auto"), + "Flatbed", + Sane.I18N ("Flatbed"), + "FlatBed", + "Normal", + Sane.I18N ("Normal") + }; + + string[] adf_sources = + { + "Automatic Document Feeder", + Sane.I18N ("Automatic Document Feeder"), + "ADF", + "Automatic Document Feeder(left aligned)", /* Seen in the proprietary brother3 driver */ + "Automatic Document Feeder(centrally aligned)" /* Seen in the proprietary brother3 driver */ + }; + + string[] adf_front_sources = + { + "ADF Front", + Sane.I18N ("ADF Front") + }; + + string[] adf_back_sources = + { + "ADF Back", + Sane.I18N ("ADF Back") + }; + + string[] adf_duplex_sources = + { + "ADF Duplex", + Sane.I18N ("ADF Duplex") + }; + + switch (job.type) + { + case ScanType.SINGLE: + if (!set_default_option (handle, option, index)) + if (!set_constrained_string_option (handle, option, index, flatbed_sources, null)) + warning ("Unable to set single page source, please file a bug"); + break; + case ScanType.ADF_FRONT: + if (!set_constrained_string_option (handle, option, index, adf_front_sources, null)) + if (!!set_constrained_string_option (handle, option, index, adf_sources, null)) + warning ("Unable to set front ADF source, please file a bug"); + break; + case ScanType.ADF_BACK: + if (!set_constrained_string_option (handle, option, index, adf_back_sources, null)) + if (!set_constrained_string_option (handle, option, index, adf_sources, null)) + warning ("Unable to set back ADF source, please file a bug"); + break; + case ScanType.ADF_BOTH: + if (!set_constrained_string_option (handle, option, index, adf_duplex_sources, null)) + if (!set_constrained_string_option (handle, option, index, adf_sources, null)) + warning ("Unable to set duplex ADF source, please file a bug"); + break; + } + } + else if (option.name == "duplex") + { + if (option.type == Sane.ValueType.BOOL) + set_bool_option (handle, option, index, job.type == ScanType.ADF_BOTH, null); + } + else if (option.name == "batch-scan") + { + if (option.type == Sane.ValueType.BOOL) + set_bool_option (handle, option, index, job.type != ScanType.SINGLE, null); + } + else if (option.name == Sane.NAME_BIT_DEPTH) + { + if (job.depth > 0) + set_int_option (handle, option, index, job.depth, null); + } + else if (option.name == Sane.NAME_SCAN_MODE) + { + /* The names of scan modes often used in drivers, as taken from the sane-backends source */ + string[] color_scan_modes = + { + Sane.VALUE_SCAN_MODE_COLOR, + "Color", + "24bit Color" /* Seen in the proprietary brother3 driver */ + }; + string[] gray_scan_modes = + { + Sane.VALUE_SCAN_MODE_GRAY, + "Gray", + "Grayscale", + Sane.I18N ("Grayscale"), + "True Gray" /* Seen in the proprietary brother3 driver */ + }; + string[] lineart_scan_modes = + { + Sane.VALUE_SCAN_MODE_LINEART, + "Lineart", + "LineArt", + Sane.I18N ("LineArt"), + "Black & White", + Sane.I18N ("Black & White"), + "Binary", + Sane.I18N ("Binary"), + "Thresholded", + Sane.VALUE_SCAN_MODE_GRAY, + "Gray", + "Grayscale", + Sane.I18N ("Grayscale"), + "True Gray" /* Seen in the proprietary brother3 driver */ + }; + + switch (job.scan_mode) + { + case ScanMode.COLOR: + if (!set_constrained_string_option (handle, option, index, color_scan_modes, null)) + warning ("Unable to set Color mode, please file a bug"); + break; + case ScanMode.GRAY: + if (!set_constrained_string_option (handle, option, index, gray_scan_modes, null)) + warning ("Unable to set Gray mode, please file a bug"); + break; + case ScanMode.LINEART: + if (!set_constrained_string_option (handle, option, index, lineart_scan_modes, null)) + warning ("Unable to set Lineart mode, please file a bug"); + break; + default: + break; + } + } + /* Disable compression, we will compress after scanning */ + else if (option.name == "compression") + { + string[] disable_compression_names = + { + Sane.I18N ("None"), + Sane.I18N ("none"), + "None", + "none" + }; + + if (!set_constrained_string_option (handle, option, index, disable_compression_names, null)) + warning ("Unable to disable compression, please file a bug"); + } + else if (option.name == Sane.NAME_SCAN_BR_X) + br_x_option_index = index; + else if (option.name == Sane.NAME_SCAN_BR_Y) + br_y_option_index = index; + else if (option.name == Sane.NAME_PAGE_WIDTH) + { + if (job.page_width > 0.0) + { + if (option.type == Sane.ValueType.FIXED) + set_fixed_option (handle, option, index, job.page_width / 10.0, null); + else + set_int_option (handle, option, index, job.page_width / 10, null); + } + } + else if (option.name == Sane.NAME_PAGE_HEIGHT) + { + if (job.page_height > 0.0) + { + if (option.type == Sane.ValueType.FIXED) + set_fixed_option (handle, option, index, job.page_height / 10.0, null); + else + set_int_option (handle, option, index, job.page_height / 10, null); + } + } + + /* Test scanner options (hoping will not effect other scanners...) */ + if (current_device == "test") + { + if (option.name == "hand-scanner") + set_bool_option (handle, option, index, false, null); + else if (option.name == "three-pass") + set_bool_option (handle, option, index, false, null); + else if (option.name == "test-picture") + set_string_option (handle, option, index, "Color pattern", null); + else if (option.name == "read-delay") + set_bool_option (handle, option, index, true, null); + else if (option.name == "read-delay-duration") + set_int_option (handle, option, index, 200000, null); + } + } + + private void do_complete_document () + { + job_queue.remove_link (job_queue); + + state = ScanState.IDLE; + + /* Continue onto the next job */ + if (job_queue != null) + { + state = ScanState.OPEN; + return; + } + + /* Trigger timeout to close */ + // TODO + + notify (new NotifyDocumentDone ()); + set_scanning (false); + } + + private void do_start () + { + Sane.Status status; + + notify (new NotifyExpectPage ()); + + status = Sane.start (handle); + debug ("sane_start (page=%d, pass=%d) -> %s", page_number, pass_number, Sane.status_to_string (status)); + if (status == Sane.Status.GOOD) + state = ScanState.GET_PARAMETERS; + else if (status == Sane.Status.NO_DOCS) + do_complete_document (); + else + { + warning ("Unable to start device: %s", Sane.strstatus (status)); + fail_scan (status, + /* Error display when unable to start scan */ + _("Unable to start scan")); + } + } + + private void do_get_parameters () + { + var status = Sane.get_parameters (handle, out parameters); + debug ("sane_get_parameters () -> %s", Sane.status_to_string (status)); + if (status != Sane.Status.GOOD) + { + warning ("Unable to get device parameters: %s", Sane.strstatus (status)); + fail_scan (status, + /* Error displayed when communication with scanner broken */ + _("Error communicating with scanner")); + return; + } + + var job = (ScanJob) job_queue.data; + + debug ("Parameters: format=%s last_frame=%s bytes_per_line=%d pixels_per_line=%d lines=%d depth=%d", + Sane.frame_to_string (parameters.format), + parameters.last_frame ? "SANE_TRUE" : "SANE_FALSE", + parameters.bytes_per_line, + parameters.pixels_per_line, + parameters.lines, + parameters.depth); + + var info = new ScanPageInfo (); + info.width = parameters.pixels_per_line; + info.height = parameters.lines; + info.depth = parameters.depth; + /* Reduce bit depth if requested lower than received */ + // FIXME: This a hack and only works on 8 bit gray to 2 bit gray + if (parameters.depth == 8 && parameters.format == Sane.Frame.GRAY && job.depth == 2 && job.scan_mode == ScanMode.GRAY) + info.depth = job.depth; + info.n_channels = parameters.format == Sane.Frame.GRAY ? 1 : 3; + info.dpi = job.dpi; // FIXME: This is the requested DPI, not the actual DPI + info.device = current_device; + + if (page_number != notified_page) + { + notify (new NotifyGotPageInfo (info)); + notified_page = page_number; + } + + /* Prepare for read */ + var buffer_size = parameters.bytes_per_line + 1; /* Use +1 so buffer is not resized if driver returns one line per read */ + buffer = new uchar[buffer_size]; + n_used = 0; + line_count = 0; + pass_number = 0; + state = ScanState.READ; + } + + private void do_complete_page () + { + notify (new NotifyPageDone ()); + + var job = (ScanJob) job_queue.data; + + /* If multi-pass then scan another page */ + if (!parameters.last_frame) + { + pass_number++; + state = ScanState.START; + return; + } + + /* Go back for another page */ + if (job.type != ScanType.SINGLE) + { + page_number++; + pass_number = 0; + notify (new NotifyPageDone ()); + state = ScanState.START; + return; + } + + Sane.cancel (handle); + debug ("sane_cancel ()"); + + do_complete_document (); + } + + private void do_read () + { + var job = (ScanJob) job_queue.data; + + /* Read as many bytes as we expect */ + var n_to_read = buffer.length - n_used; + + Sane.Int n_read; + var b = (uchar *) buffer; + var status = Sane.read (handle, (uint8[]) (b + n_used), (Sane.Int) n_to_read, out n_read); + debug ("sane_read (%d) -> (%s, %d)", n_to_read, Sane.status_to_string (status), n_read); + + /* Completed read */ + if (status == Sane.Status.EOF) + { + if (parameters.lines > 0 && line_count != parameters.lines) + warning ("Scan completed with %d lines, expected %d lines", parameters.lines, parameters.lines); + if (n_used > 0) + warning ("Scan complete with %d bytes of unused data", n_used); + do_complete_page (); + return; + } + + /* Communication error */ + if (status != Sane.Status.GOOD) + { + warning ("Unable to read frame from device: %s", Sane.strstatus (status)); + fail_scan (status, + /* Error displayed when communication with scanner broken */ + _("Error communicating with scanner")); + return; + } + + bool full_read = false; + if (n_used == 0 && n_read == buffer.length) + full_read = true; + n_used += n_read; + + /* Feed out lines */ + if (n_used >= parameters.bytes_per_line) + { + var line = new ScanLine (); + switch (parameters.format) + { + case Sane.Frame.GRAY: + line.channel = 0; + break; + case Sane.Frame.RGB: + line.channel = -1; + break; + case Sane.Frame.RED: + line.channel = 0; + break; + case Sane.Frame.GREEN: + line.channel = 1; + break; + case Sane.Frame.BLUE: + line.channel = 2; + break; + } + line.width = parameters.pixels_per_line; + line.depth = parameters.depth; + line.data = (owned) buffer; + line.data_length = parameters.bytes_per_line; + line.number = line_count; + line.n_lines = n_used / line.data_length; + + line_count += line.n_lines; + + /* Increase buffer size if did full read */ + var buffer_size = buffer.length; + if (full_read) + buffer_size += parameters.bytes_per_line; + + buffer = new uchar[buffer_size]; + var n_remaining = n_used - (line.n_lines * line.data_length); + n_used = 0; + for (var i = 0; i < n_remaining; i++) + { + buffer[i] = line.data[i + (line.n_lines * line.data_length)]; + n_used++; + } + + /* Reduce bit depth if requested lower than received */ + // FIXME: This a hack and only works on 8 bit gray to 2 bit gray + if (parameters.depth == 8 && parameters.format == Sane.Frame.GRAY && + job.depth == 2 && job.scan_mode == ScanMode.GRAY) + { + uchar block = 0; + var write_offset = 0; + var block_shift = 6; + for (var i = 0; i < line.n_lines; i++) + { + var offset = i * line.data_length; + for (var x = 0; x < line.width; x++) + { + var p = line.data[offset + x]; + + uchar sample; + if (p >= 192) + sample = 3; + else if (p >= 128) + sample = 2; + else if (p >= 64) + sample = 1; + else + sample = 0; + + block |= sample << block_shift; + if (block_shift == 0) + { + line.data[write_offset] = block; + write_offset++; + block = 0; + block_shift = 6; + } + else + block_shift -= 2; + } + + /* Finish each line on a byte boundary */ + if (block_shift != 6) + { + line.data[write_offset] = block; + write_offset++; + block = 0; + block_shift = 6; + } + } + + line.data_length = (line.width * 2 + 7) / 8; + } + + notify (new NotifyGotLine (line)); + } + } + + private void* scan_thread () + { + state = ScanState.IDLE; + + Sane.Int version_code; + var status = Sane.init (out version_code, authorization_cb); + debug ("sane_init () -> %s", Sane.status_to_string (status)); + if (status != Sane.Status.GOOD) + { + warning ("Unable to initialize SANE backend: %s", Sane.strstatus(status)); + return null; + } + debug ("SANE version %d.%d.%d", + Sane.VERSION_MAJOR(version_code), + Sane.VERSION_MINOR(version_code), + Sane.VERSION_BUILD(version_code)); + + /* Scan for devices on first start */ + redetect (); + + while (handle_requests ()) + { + switch (state) + { + case ScanState.IDLE: + if (job_queue != null) + { + set_scanning (true); + state = ScanState.OPEN; + } + break; + case ScanState.REDETECT: + do_redetect (); + break; + case ScanState.OPEN: + do_open (); + break; + case ScanState.GET_OPTION: + do_get_option (); + break; + case ScanState.START: + do_start (); + break; + case ScanState.GET_PARAMETERS: + do_get_parameters (); + break; + case ScanState.READ: + do_read (); + break; + } + } + + return null; + } + + public void start () + { + try + { + thread = Thread.create<void*> (scan_thread, true); + } + catch (Error e) + { + critical ("Unable to create thread: %s", e.message); + } + } + + public void redetect () + { + if (need_redetect) + return; + need_redetect = true; + + debug ("Requesting redetection of scan devices"); + + request_queue.push (new RequestRedetect ()); + } + + public bool is_scanning () + { + return scanning; + } + + private string get_scan_mode_string (ScanMode mode) + { + switch (mode) + { + case ScanMode.DEFAULT: + return "ScanMode.DEFAULT"; + case ScanMode.COLOR: + return "ScanMode.COLOR"; + case ScanMode.GRAY: + return "ScanMode.GRAY"; + case ScanMode.LINEART: + return "ScanMode.LINEART"; + default: + return "%d".printf (mode); + } + } + + private string get_scan_type_string (ScanType type) + { + switch (type) + { + case ScanType.SINGLE: + return "ScanType.SINGLE"; + case ScanType.ADF_FRONT: + return "ScanType.ADF_FRONT"; + case ScanType.ADF_BACK: + return "ScanType.ADF_BACK"; + case ScanType.ADF_BOTH: + return "ScanType.ADF_BOTH"; + default: + return "%d".printf (type); + } + } + + public void scan (string? device, ScanOptions options) + { + debug ("Scanner.scan (\"%s\", dpi=%d, scan_mode=%s, depth=%d, type=%s, paper_width=%d, paper_height=%d)", + device != null ? device : "(null)", options.dpi, get_scan_mode_string (options.scan_mode), options.depth, + get_scan_type_string (options.type), options.paper_width, options.paper_height); + var request = new RequestStartScan (); + request.job = new ScanJob (); + request.job.device = device; + request.job.dpi = options.dpi; + request.job.scan_mode = options.scan_mode; + request.job.depth = options.depth; + request.job.type = options.type; + request.job.page_width = options.paper_width; + request.job.page_height = options.paper_height; + request_queue.push (request); + } + + public void cancel () + { + request_queue.push (new RequestCancel ()); + } + + public void free () + { + debug ("Stopping scan thread"); + + request_queue.push (new RequestQuit ()); + + if (thread != null) + thread.join (); + + Sane.exit (); + debug ("sane_exit ()"); + } +} diff --git a/src/simple-scan.c b/src/simple-scan.c index bb7e036..1f1f599 100644 --- a/src/simple-scan.c +++ b/src/simple-scan.c @@ -1,7 +1,10 @@ +/* simple-scan.c generated by valac 0.13.1, the Vala compiler + * generated from simple-scan.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later @@ -9,608 +12,1507 @@ * license. */ -#include <stdlib.h> +#include <glib.h> +#include <glib-object.h> +#include <gudev/gudev.h> #include <stdio.h> -#include <glib/gi18n.h> -#include <gtk/gtk.h> +#include <stdlib.h> +#include <string.h> +#include <float.h> +#include <math.h> +#include <sane/sane.h> +#include <glib/gi18n-lib.h> +#include <glib/gstdio.h> #include <unistd.h> -#include <gudev/gudev.h> -#include <dbus/dbus-glib.h> +#include <gio/gio.h> +#include <gtk/gtk.h> +#include <locale.h> +#include <config.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_APPLICATION (application_get_type ()) +#define APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_APPLICATION, Application)) +#define APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_APPLICATION, ApplicationClass)) +#define IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_APPLICATION)) +#define IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_APPLICATION)) +#define APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_APPLICATION, ApplicationClass)) + +typedef struct _Application Application; +typedef struct _ApplicationClass ApplicationClass; +typedef struct _ApplicationPrivate ApplicationPrivate; + +#define TYPE_SCAN_DEVICE (scan_device_get_type ()) +#define SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_DEVICE, ScanDevice)) +#define SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_DEVICE, ScanDeviceClass)) +#define IS_SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_DEVICE)) +#define IS_SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_DEVICE)) +#define SCAN_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_DEVICE, ScanDeviceClass)) + +typedef struct _ScanDevice ScanDevice; +typedef struct _ScanDeviceClass ScanDeviceClass; + +#define TYPE_SIMPLE_SCAN (simple_scan_get_type ()) +#define SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SIMPLE_SCAN, SimpleScan)) +#define SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SIMPLE_SCAN, SimpleScanClass)) +#define IS_SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SIMPLE_SCAN)) +#define IS_SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SIMPLE_SCAN)) +#define SIMPLE_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SIMPLE_SCAN, SimpleScanClass)) + +typedef struct _SimpleScan SimpleScan; +typedef struct _SimpleScanClass SimpleScanClass; + +#define TYPE_SCANNER (scanner_get_type ()) +#define SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCANNER, Scanner)) +#define SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCANNER, ScannerClass)) +#define IS_SCANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCANNER)) +#define IS_SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCANNER)) +#define SCANNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCANNER, ScannerClass)) + +typedef struct _Scanner Scanner; +typedef struct _ScannerClass ScannerClass; + +#define TYPE_BOOK (book_get_type ()) +#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book)) +#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass)) +#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK)) +#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK)) +#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass)) + +typedef struct _Book Book; +typedef struct _BookClass BookClass; +#define _scan_device_unref0(var) ((var == NULL) ? NULL : (var = (scan_device_unref (var), NULL))) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _simple_scan_unref0(var) ((var == NULL) ? NULL : (var = (simple_scan_unref (var), NULL))) +#define _scanner_unref0(var) ((var == NULL) ? NULL : (var = (scanner_unref (var), NULL))) +#define _book_unref0(var) ((var == NULL) ? NULL : (var = (book_unref (var), NULL))) + +#define TYPE_SCAN_OPTIONS (scan_options_get_type ()) +#define SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_OPTIONS, ScanOptions)) +#define SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_OPTIONS, ScanOptionsClass)) +#define IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_OPTIONS)) +#define IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_OPTIONS)) +#define SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_OPTIONS, ScanOptionsClass)) + +typedef struct _ScanOptions ScanOptions; +typedef struct _ScanOptionsClass ScanOptionsClass; + +#define TYPE_SCAN_PAGE_INFO (scan_page_info_get_type ()) +#define SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfo)) +#define SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) +#define IS_SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_PAGE_INFO)) +#define IS_SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_PAGE_INFO)) +#define SCAN_PAGE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) + +typedef struct _ScanPageInfo ScanPageInfo; +typedef struct _ScanPageInfoClass ScanPageInfoClass; + +#define TYPE_SCAN_LINE (scan_line_get_type ()) +#define SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_LINE, ScanLine)) +#define SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_LINE, ScanLineClass)) +#define IS_SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_LINE)) +#define IS_SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_LINE)) +#define SCAN_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_LINE, ScanLineClass)) + +typedef struct _ScanLine ScanLine; +typedef struct _ScanLineClass ScanLineClass; +typedef struct _ScanDevicePrivate ScanDevicePrivate; +#define __g_list_free__scan_device_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__scan_device_unref0_ (var), NULL))) +#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) +#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL))) +typedef struct _ScanPageInfoPrivate ScanPageInfoPrivate; +typedef struct _ScanOptionsPrivate ScanOptionsPrivate; + +#define TYPE_SCAN_MODE (scan_mode_get_type ()) + +#define TYPE_SCAN_TYPE (scan_type_get_type ()) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +#define _g_option_context_free0(var) ((var == NULL) ? NULL : (var = (g_option_context_free (var), NULL))) +#define _g_timer_destroy0(var) ((var == NULL) ? NULL : (var = (g_timer_destroy (var), NULL))) +#define _fclose0(var) ((var == NULL) ? NULL : (var = (fclose (var), NULL))) +#define _application_unref0(var) ((var == NULL) ? NULL : (var = (application_unref (var), NULL))) +typedef struct _ParamSpecApplication ParamSpecApplication; + +struct _Application { + GTypeInstance parent_instance; + volatile int ref_count; + ApplicationPrivate * priv; +}; + +struct _ApplicationClass { + GTypeClass parent_class; + void (*finalize) (Application *self); +}; + +struct _ApplicationPrivate { + ScanDevice* default_device; + gboolean have_devices; + GUdevClient* udev_client; + SimpleScan* ui; + Scanner* scanner; + Book* book; +}; + +struct _ScanDevice { + GTypeInstance parent_instance; + volatile int ref_count; + ScanDevicePrivate * priv; + gchar* name; + gchar* label; +}; + +struct _ScanDeviceClass { + GTypeClass parent_class; + void (*finalize) (ScanDevice *self); +}; + +typedef enum { + SCAN_DIRECTION_TOP_TO_BOTTOM, + SCAN_DIRECTION_LEFT_TO_RIGHT, + SCAN_DIRECTION_BOTTOM_TO_TOP, + SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _ScanPageInfo { + GTypeInstance parent_instance; + volatile int ref_count; + ScanPageInfoPrivate * priv; + gint width; + gint height; + gint depth; + gint n_channels; + gdouble dpi; + gchar* device; +}; + +struct _ScanPageInfoClass { + GTypeClass parent_class; + void (*finalize) (ScanPageInfo *self); +}; + +typedef enum { + SCAN_MODE_DEFAULT, + SCAN_MODE_COLOR, + SCAN_MODE_GRAY, + SCAN_MODE_LINEART +} ScanMode; + +typedef enum { + SCAN_TYPE_SINGLE, + SCAN_TYPE_ADF_FRONT, + SCAN_TYPE_ADF_BACK, + SCAN_TYPE_ADF_BOTH +} ScanType; + +struct _ScanOptions { + GTypeInstance parent_instance; + volatile int ref_count; + ScanOptionsPrivate * priv; + gint dpi; + ScanMode scan_mode; + gint depth; + ScanType type; + gint paper_width; + gint paper_height; +}; + +struct _ScanOptionsClass { + GTypeClass parent_class; + void (*finalize) (ScanOptions *self); +}; + +struct _ParamSpecApplication { + GParamSpec parent_instance; +}; + + +static gpointer application_parent_class = NULL; +static gboolean application_show_version; +static gboolean application_show_version = FALSE; +static gboolean application_debug_enabled; +static gboolean application_debug_enabled = FALSE; +static GTimer* application_log_timer; +static GTimer* application_log_timer = NULL; +static FILE* application_log_file; +static FILE* application_log_file = NULL; + +gpointer application_ref (gpointer instance); +void application_unref (gpointer instance); +GParamSpec* param_spec_application (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_application (GValue* value, gpointer v_object); +void value_take_application (GValue* value, gpointer v_object); +gpointer value_get_application (const GValue* value); +GType application_get_type (void) G_GNUC_CONST; +gpointer scan_device_ref (gpointer instance); +void scan_device_unref (gpointer instance); +GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_device (GValue* value, gpointer v_object); +void value_take_scan_device (GValue* value, gpointer v_object); +gpointer value_get_scan_device (const GValue* value); +GType scan_device_get_type (void) G_GNUC_CONST; +gpointer simple_scan_ref (gpointer instance); +void simple_scan_unref (gpointer instance); +GParamSpec* param_spec_simple_scan (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_simple_scan (GValue* value, gpointer v_object); +void value_take_simple_scan (GValue* value, gpointer v_object); +gpointer value_get_simple_scan (const GValue* value); +GType simple_scan_get_type (void) G_GNUC_CONST; +gpointer scanner_ref (gpointer instance); +void scanner_unref (gpointer instance); +GParamSpec* param_spec_scanner (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scanner (GValue* value, gpointer v_object); +void value_take_scanner (GValue* value, gpointer v_object); +gpointer value_get_scanner (const GValue* value); +GType scanner_get_type (void) G_GNUC_CONST; +gpointer book_ref (gpointer instance); +void book_unref (gpointer instance); +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_book (GValue* value, gpointer v_object); +void value_take_book (GValue* value, gpointer v_object); +gpointer value_get_book (const GValue* value); +GType book_get_type (void) G_GNUC_CONST; +#define APPLICATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_APPLICATION, ApplicationPrivate)) +enum { + APPLICATION_DUMMY_PROPERTY +}; +Application* application_new (ScanDevice* device); +Application* application_construct (GType object_type, ScanDevice* device); +SimpleScan* simple_scan_new (void); +SimpleScan* simple_scan_construct (GType object_type); +Book* simple_scan_get_book (SimpleScan* self); +gpointer scan_options_ref (gpointer instance); +void scan_options_unref (gpointer instance); +GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_options (GValue* value, gpointer v_object); +void value_take_scan_options (GValue* value, gpointer v_object); +gpointer value_get_scan_options (const GValue* value); +GType scan_options_get_type (void) G_GNUC_CONST; +static void application_scan_cb (Application* self, SimpleScan* ui, const gchar* device, ScanOptions* options); +static void _application_scan_cb_simple_scan_start_scan (SimpleScan* _sender, const gchar* device, ScanOptions* options, gpointer self); +static void application_cancel_cb (Application* self, SimpleScan* ui); +static void _application_cancel_cb_simple_scan_stop_scan (SimpleScan* _sender, gpointer self); +static void application_email_cb (Application* self, SimpleScan* ui, const gchar* profile); +static void _application_email_cb_simple_scan_email (SimpleScan* _sender, const gchar* profile, gpointer self); +static void application_quit_cb (Application* self, SimpleScan* ui); +static void _application_quit_cb_simple_scan_quit (SimpleScan* _sender, gpointer self); +Scanner* scanner_get_instance (void); +static void application_update_scan_devices_cb (Application* self, Scanner* scanner, GList* devices); +static void _application_update_scan_devices_cb_scanner_update_devices (Scanner* _sender, GList* devices, gpointer self); +static void application_authorize_cb (Application* self, Scanner* scanner, const gchar* resource); +static void _application_authorize_cb_scanner_request_authorization (Scanner* _sender, const gchar* resource, gpointer self); +static void application_scanner_new_page_cb (Application* self, Scanner* scanner); +static void _application_scanner_new_page_cb_scanner_expect_page (Scanner* _sender, gpointer self); +gpointer scan_page_info_ref (gpointer instance); +void scan_page_info_unref (gpointer instance); +GParamSpec* param_spec_scan_page_info (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_page_info (GValue* value, gpointer v_object); +void value_take_scan_page_info (GValue* value, gpointer v_object); +gpointer value_get_scan_page_info (const GValue* value); +GType scan_page_info_get_type (void) G_GNUC_CONST; +static void application_scanner_page_info_cb (Application* self, Scanner* scanner, ScanPageInfo* info); +static void _application_scanner_page_info_cb_scanner_got_page_info (Scanner* _sender, ScanPageInfo* info, gpointer self); +gpointer scan_line_ref (gpointer instance); +void scan_line_unref (gpointer instance); +GParamSpec* param_spec_scan_line (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_line (GValue* value, gpointer v_object); +void value_take_scan_line (GValue* value, gpointer v_object); +gpointer value_get_scan_line (const GValue* value); +GType scan_line_get_type (void) G_GNUC_CONST; +static void application_scanner_line_cb (Application* self, Scanner* scanner, ScanLine* line); +static void _application_scanner_line_cb_scanner_got_line (Scanner* _sender, ScanLine* line, gpointer self); +static void application_scanner_page_done_cb (Application* self, Scanner* scanner); +static void _application_scanner_page_done_cb_scanner_page_done (Scanner* _sender, gpointer self); +static void application_scanner_document_done_cb (Application* self, Scanner* scanner); +static void _application_scanner_document_done_cb_scanner_document_done (Scanner* _sender, gpointer self); +static void application_scanner_failed_cb (Application* self, Scanner* scanner, gint error_code, const gchar* error_string); +static void _application_scanner_failed_cb_scanner_scan_failed (Scanner* _sender, gint error_code, const gchar* error_string, gpointer self); +static void application_scanner_scanning_changed_cb (Application* self, Scanner* scanner); +static void _application_scanner_scanning_changed_cb_scanner_scanning_changed (Scanner* _sender, gpointer self); +static void application_on_uevent (Application* self, GUdevClient* client, const gchar* action, GUdevDevice* device); +static void _application_on_uevent_g_udev_client_uevent (GUdevClient* _sender, const gchar* action, GUdevDevice* device, gpointer self); +void simple_scan_set_scan_devices (SimpleScan* self, GList* devices); +void simple_scan_set_selected_device (SimpleScan* self, const gchar* device); +static void _scan_device_unref0_ (gpointer var); +static void _g_list_free__scan_device_unref0_ (GList* self); +void application_start (Application* self); +void simple_scan_start (SimpleScan* self); +void scanner_start (Scanner* self); +void simple_scan_authorize (SimpleScan* self, const gchar* resource, gchar** username, gchar** password); +void scanner_authorize (Scanner* self, const gchar* username, const gchar* password); +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +static Page* application_append_page (Application* self); +Page* book_get_page (Book* self, gint page_number); +gboolean page_has_data (Page* self); +void simple_scan_set_selected_page (SimpleScan* self, Page* page); +void page_start (Page* self); +GType scan_direction_get_type (void) G_GNUC_CONST; +ScanDirection page_get_scan_direction (Page* self); +gint page_get_width (Page* self); +gint page_get_height (Page* self); +gint page_get_dpi (Page* self); +gboolean page_has_crop (Page* self); +gchar* page_get_named_crop (Page* self); +void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height); +Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction); +void page_set_named_crop (Page* self, const gchar* name); +void page_set_custom_crop (Page* self, gint width, gint height); +void page_move_crop (Page* self, gint x, gint y); +static gchar* application_get_profile_for_device (Application* self, const gchar* device_name); +void page_set_page_info (Page* self, ScanPageInfo* info); +void page_set_color_profile (Page* self, const gchar* color_profile); +guint book_get_n_pages (Book* self); +void page_parse_scan_line (Page* self, ScanLine* line); +void page_finish (Page* self); +static void application_remove_empty_page (Application* self); +void book_delete_page (Book* self, Page* page); +void simple_scan_show_error (SimpleScan* self, const gchar* error_title, const gchar* error_text, gboolean change_scanner_hint); +void simple_scan_set_scanning (SimpleScan* self, gboolean scanning); +gboolean scanner_is_scanning (Scanner* self); +GType scan_mode_get_type (void) G_GNUC_CONST; +GType scan_type_get_type (void) G_GNUC_CONST; +void simple_scan_set_default_file_name (SimpleScan* self, const gchar* default_file_name); +void scanner_scan (Scanner* self, const gchar* device, ScanOptions* options); +void scanner_cancel (Scanner* self); +static gchar* application_get_temporary_filename (Application* self, const gchar* prefix, const gchar* extension); +void book_save (Book* self, const gchar* type, GFile* file, GError** error); +void page_save (Page* self, const gchar* type, GFile* file, GError** error); +void scanner_free (Scanner* self); +static void application_log_cb (const gchar* log_domain, GLogLevelFlags log_level, const gchar* message); +void scanner_redetect (Scanner* self); +gint application_main (gchar** args, int args_length1); +ScanDevice* scan_device_new (void); +ScanDevice* scan_device_construct (GType object_type); +static void _application_log_cb_glog_func (const gchar* log_domain, GLogLevelFlags log_levels, const gchar* message, gpointer self); +static void application_finalize (Application* obj); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); + +const GOptionEntry APPLICATION_options[3] = {{"version", 'v', 0, G_OPTION_ARG_NONE, &application_show_version, "Show release version", NULL}, {"debug", 'd', 0, G_OPTION_ARG_NONE, &application_debug_enabled, "Print debugging messages", NULL}, {NULL}}; + +static gpointer _scan_device_ref0 (gpointer self) { + return self ? scan_device_ref (self) : NULL; +} + + +static void _application_scan_cb_simple_scan_start_scan (SimpleScan* _sender, const gchar* device, ScanOptions* options, gpointer self) { + application_scan_cb (self, _sender, device, options); +} + + +static void _application_cancel_cb_simple_scan_stop_scan (SimpleScan* _sender, gpointer self) { + application_cancel_cb (self, _sender); +} + + +static void _application_email_cb_simple_scan_email (SimpleScan* _sender, const gchar* profile, gpointer self) { + application_email_cb (self, _sender, profile); +} + + +static void _application_quit_cb_simple_scan_quit (SimpleScan* _sender, gpointer self) { + application_quit_cb (self, _sender); +} + + +static void _application_update_scan_devices_cb_scanner_update_devices (Scanner* _sender, GList* devices, gpointer self) { + application_update_scan_devices_cb (self, _sender, devices); +} + + +static void _application_authorize_cb_scanner_request_authorization (Scanner* _sender, const gchar* resource, gpointer self) { + application_authorize_cb (self, _sender, resource); +} + + +static void _application_scanner_new_page_cb_scanner_expect_page (Scanner* _sender, gpointer self) { + application_scanner_new_page_cb (self, _sender); +} + + +static void _application_scanner_page_info_cb_scanner_got_page_info (Scanner* _sender, ScanPageInfo* info, gpointer self) { + application_scanner_page_info_cb (self, _sender, info); +} + + +static void _application_scanner_line_cb_scanner_got_line (Scanner* _sender, ScanLine* line, gpointer self) { + application_scanner_line_cb (self, _sender, line); +} + + +static void _application_scanner_page_done_cb_scanner_page_done (Scanner* _sender, gpointer self) { + application_scanner_page_done_cb (self, _sender); +} + + +static void _application_scanner_document_done_cb_scanner_document_done (Scanner* _sender, gpointer self) { + application_scanner_document_done_cb (self, _sender); +} + + +static void _application_scanner_failed_cb_scanner_scan_failed (Scanner* _sender, gint error_code, const gchar* error_string, gpointer self) { + application_scanner_failed_cb (self, _sender, error_code, error_string); +} + + +static void _application_scanner_scanning_changed_cb_scanner_scanning_changed (Scanner* _sender, gpointer self) { + application_scanner_scanning_changed_cb (self, _sender); +} + + +static void _application_on_uevent_g_udev_client_uevent (GUdevClient* _sender, const gchar* action, GUdevDevice* device, gpointer self) { + application_on_uevent (self, _sender, action, device); +} + -#include <sane/sane.h> // For SANE_STATUS_CANCELLED +static void _scan_device_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (scan_device_unref (var), NULL)); +} -#include "ui.h" -#include "scanner.h" -#include "book.h" - - -static ScanDevice *default_device = NULL; - -static gboolean have_devices = FALSE; - -static GUdevClient *udev_client; -static SimpleScan *ui; +static void _g_list_free__scan_device_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _scan_device_unref0_, NULL); + g_list_free (self); +} -static Scanner *scanner; -static Book *book; +Application* application_construct (GType object_type, ScanDevice* device) { + Application* self = NULL; + ScanDevice* _tmp0_; + SimpleScan* _tmp1_ = NULL; + Book* _tmp2_ = NULL; + Scanner* _tmp3_ = NULL; + gchar* _tmp4_; + gchar** _tmp5_ = NULL; + gchar** subsystems; + gint subsystems_length1; + gint _subsystems_size_; + GUdevClient* _tmp6_ = NULL; + self = (Application*) g_type_create_instance (object_type); + _tmp0_ = _scan_device_ref0 (device); + _scan_device_unref0 (self->priv->default_device); + self->priv->default_device = _tmp0_; + _tmp1_ = simple_scan_new (); + _simple_scan_unref0 (self->priv->ui); + self->priv->ui = _tmp1_; + _tmp2_ = simple_scan_get_book (self->priv->ui); + _book_unref0 (self->priv->book); + self->priv->book = _tmp2_; + g_signal_connect (self->priv->ui, "start-scan", (GCallback) _application_scan_cb_simple_scan_start_scan, self); + g_signal_connect (self->priv->ui, "stop-scan", (GCallback) _application_cancel_cb_simple_scan_stop_scan, self); + g_signal_connect (self->priv->ui, "email", (GCallback) _application_email_cb_simple_scan_email, self); + g_signal_connect (self->priv->ui, "quit", (GCallback) _application_quit_cb_simple_scan_quit, self); + _tmp3_ = scanner_get_instance (); + _scanner_unref0 (self->priv->scanner); + self->priv->scanner = _tmp3_; + g_signal_connect (self->priv->scanner, "update-devices", (GCallback) _application_update_scan_devices_cb_scanner_update_devices, self); + g_signal_connect (self->priv->scanner, "request-authorization", (GCallback) _application_authorize_cb_scanner_request_authorization, self); + g_signal_connect (self->priv->scanner, "expect-page", (GCallback) _application_scanner_new_page_cb_scanner_expect_page, self); + g_signal_connect (self->priv->scanner, "got-page-info", (GCallback) _application_scanner_page_info_cb_scanner_got_page_info, self); + g_signal_connect (self->priv->scanner, "got-line", (GCallback) _application_scanner_line_cb_scanner_got_line, self); + g_signal_connect (self->priv->scanner, "page-done", (GCallback) _application_scanner_page_done_cb_scanner_page_done, self); + g_signal_connect (self->priv->scanner, "document-done", (GCallback) _application_scanner_document_done_cb_scanner_document_done, self); + g_signal_connect (self->priv->scanner, "scan-failed", (GCallback) _application_scanner_failed_cb_scanner_scan_failed, self); + g_signal_connect (self->priv->scanner, "scanning-changed", (GCallback) _application_scanner_scanning_changed_cb_scanner_scanning_changed, self); + _tmp4_ = g_strdup ("usb"); + _tmp5_ = g_new0 (gchar*, 2 + 1); + _tmp5_[0] = _tmp4_; + _tmp5_[1] = NULL; + subsystems = _tmp5_; + subsystems_length1 = 2; + _subsystems_size_ = subsystems_length1; + _tmp6_ = g_udev_client_new (subsystems); + _g_object_unref0 (self->priv->udev_client); + self->priv->udev_client = _tmp6_; + g_signal_connect (self->priv->udev_client, "uevent", (GCallback) _application_on_uevent_g_udev_client_uevent, self); + if (self->priv->default_device != NULL) { + GList* device_list; + ScanDevice* _tmp7_; + device_list = NULL; + _tmp7_ = _scan_device_ref0 (self->priv->default_device); + device_list = g_list_append (device_list, _tmp7_); + simple_scan_set_scan_devices (self->priv->ui, device_list); + simple_scan_set_selected_device (self->priv->ui, self->priv->default_device->name); + __g_list_free__scan_device_unref0_0 (device_list); + } + subsystems = (_vala_array_free (subsystems, subsystems_length1, (GDestroyNotify) g_free), NULL); + return self; +} -static GTimer *log_timer; -static FILE *log_file; +Application* application_new (ScanDevice* device) { + return application_construct (TYPE_APPLICATION, device); +} -static gboolean debug = FALSE; +void application_start (Application* self) { + g_return_if_fail (self != NULL); + simple_scan_start (self->priv->ui); + scanner_start (self->priv->scanner); +} -static void -update_scan_devices_cb (Scanner *scanner, GList *devices) -{ - GList *devices_copy; - - devices_copy = g_list_copy (devices); - - /* If the default device is not detected add it to the list */ - if (default_device) { - GList *i; - - for (i = devices_copy; i; i = i->next) { - ScanDevice *device = i->data; - if (strcmp (device->name, default_device->name) == 0) - break; - } - - if (!i) - devices_copy = g_list_prepend (devices_copy, default_device); - } - - have_devices = devices_copy != NULL; - ui_set_scan_devices (ui, devices_copy); - - g_list_free (devices_copy); -} - - -static void -authorize_cb (Scanner *scanner, const gchar *resource) -{ - gchar *username = NULL, *password = NULL; - ui_authorize (ui, resource, &username, &password); - scanner_authorize (scanner, username, password); - g_free (username); - g_free (password); -} - - -static Page * -append_page () -{ - Page *page; - ScanDirection scan_direction = TOP_TO_BOTTOM; - gboolean do_crop = FALSE; - gchar *named_crop = NULL; - gint width = 100, height = 100, dpi = 100, cx, cy, cw, ch; - - /* Use current page if not used */ - page = book_get_page (book, -1); - if (page && !page_has_data (page)) { - ui_set_selected_page (ui, page); - page_start (page); - return page; - } - - /* Copy info from previous page */ - if (page) { - scan_direction = page_get_scan_direction (page); - width = page_get_width (page); - height = page_get_height (page); - dpi = page_get_dpi (page); - - do_crop = page_has_crop (page); - if (do_crop) { - named_crop = page_get_named_crop (page); - page_get_crop (page, &cx, &cy, &cw, &ch); - } - } - - page = book_append_page (book, width, height, dpi, scan_direction); - if (do_crop) { - if (named_crop) { - page_set_named_crop (page, named_crop); - g_free (named_crop); - } - else - page_set_custom_crop (page, cw, ch); - page_move_crop (page, cx, cy); - } - ui_set_selected_page (ui, page); - page_start (page); - - return page; -} - - -static void -scanner_new_page_cb (Scanner *scanner) -{ - append_page (); -} - - -static gchar * -get_profile_for_device (const gchar *current_device) -{ - gboolean ret; - DBusGConnection *connection; - DBusGProxy *proxy; - GError *error = NULL; - GType custom_g_type_string_string; - GPtrArray *profile_data_array = NULL; - gchar *device_id = NULL; - gchar *icc_profile = NULL; - - /* Connect to the color manager on the session bus */ - connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); - proxy = dbus_g_proxy_new_for_name (connection, - "org.gnome.ColorManager", - "/org/gnome/ColorManager", - "org.gnome.ColorManager"); - - /* Get color profile */ - device_id = g_strdup_printf ("sane:%s", current_device); - custom_g_type_string_string = dbus_g_type_get_collection ("GPtrArray", - dbus_g_type_get_struct("GValueArray", - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_INVALID)); - ret = dbus_g_proxy_call (proxy, "GetProfilesForDevice", &error, - G_TYPE_STRING, device_id, - G_TYPE_STRING, "", - G_TYPE_INVALID, - custom_g_type_string_string, &profile_data_array, - G_TYPE_INVALID); - g_object_unref (proxy); - g_free (device_id); - if (!ret) { - g_debug ("The request failed: %s", error->message); - g_error_free (error); - return NULL; - } - - if (profile_data_array->len > 0) { - GValueArray *gva; - GValue *gv = NULL; - - /* Just use the preferred profile filename */ - gva = (GValueArray *) g_ptr_array_index (profile_data_array, 0); - gv = g_value_array_get_nth (gva, 1); - icc_profile = g_value_dup_string (gv); - g_value_unset (gv); - } - else - g_debug ("There are no ICC profiles for the device sane:%s", current_device); - g_ptr_array_free (profile_data_array, TRUE); - - return icc_profile; -} - - -static void -scanner_page_info_cb (Scanner *scanner, ScanPageInfo *info) -{ - Page *page; - - g_debug ("Page is %d pixels wide, %d pixels high, %d bits per pixel", - info->width, info->height, info->depth); - /* Add a new page */ - page = append_page (); - page_set_page_info (page, info); +static void application_update_scan_devices_cb (Application* self, Scanner* scanner, GList* devices) { + GList* _tmp0_ = NULL; + GList* devices_copy; + guint _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + _tmp0_ = g_list_copy (devices); + devices_copy = _tmp0_; + if (self->priv->default_device != NULL) { + gboolean default_in_list; + default_in_list = FALSE; + { + GList* device_collection = NULL; + GList* device_it = NULL; + device_collection = devices_copy; + for (device_it = device_collection; device_it != NULL; device_it = device_it->next) { + ScanDevice* device = NULL; + device = (ScanDevice*) device_it->data; + { + if (g_strcmp0 (device->name, self->priv->default_device->name) == 0) { + default_in_list = TRUE; + break; + } + } + } + } + if (!default_in_list) { + devices_copy = g_list_prepend (devices_copy, self->priv->default_device); + } + } + _tmp1_ = g_list_length (devices_copy); + self->priv->have_devices = _tmp1_ > ((guint) 0); + simple_scan_set_scan_devices (self->priv->ui, devices_copy); + _g_list_free0 (devices_copy); +} + - /* Get ICC color profile */ - /* FIXME: The ICC profile could change */ - /* FIXME: Don't do a D-bus call for each page, cache color profiles */ - page_set_color_profile (page, get_profile_for_device (info->device)); +static void application_authorize_cb (Application* self, Scanner* scanner, const gchar* resource) { + gchar* username = NULL; + gchar* password = NULL; + gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + g_return_if_fail (resource != NULL); + simple_scan_authorize (self->priv->ui, resource, &_tmp0_, &_tmp1_); + _g_free0 (username); + username = _tmp0_; + _g_free0 (password); + password = _tmp1_; + scanner_authorize (scanner, username, password); + _g_free0 (password); + _g_free0 (username); } -static void -scanner_line_cb (Scanner *scanner, ScanLine *line) -{ - Page *page; +static Page* application_append_page (Application* self) { + Page* result = NULL; + Page* _tmp0_ = NULL; + Page* page; + gboolean _tmp1_ = FALSE; + ScanDirection scan_direction; + gboolean do_crop; + gchar* named_crop; + gint width; + gint height; + gint dpi; + gint cx; + gint cy; + gint cw; + gint ch; + Page* _tmp13_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = book_get_page (self->priv->book, -1); + page = _tmp0_; + if (page != NULL) { + gboolean _tmp2_; + _tmp2_ = page_has_data (page); + _tmp1_ = !_tmp2_; + } else { + _tmp1_ = FALSE; + } + if (_tmp1_) { + simple_scan_set_selected_page (self->priv->ui, page); + page_start (page); + result = page; + return result; + } + scan_direction = SCAN_DIRECTION_TOP_TO_BOTTOM; + do_crop = FALSE; + named_crop = NULL; + width = 100; + height = 100; + dpi = 100; + cx = 0; + cy = 0; + cw = 0; + ch = 0; + if (page != NULL) { + ScanDirection _tmp3_; + gint _tmp4_; + gint _tmp5_; + gint _tmp6_; + gboolean _tmp7_; + _tmp3_ = page_get_scan_direction (page); + scan_direction = _tmp3_; + _tmp4_ = page_get_width (page); + width = _tmp4_; + _tmp5_ = page_get_height (page); + height = _tmp5_; + _tmp6_ = page_get_dpi (page); + dpi = _tmp6_; + _tmp7_ = page_has_crop (page); + do_crop = _tmp7_; + if (do_crop) { + gchar* _tmp8_ = NULL; + gint _tmp9_; + gint _tmp10_; + gint _tmp11_; + gint _tmp12_; + _tmp8_ = page_get_named_crop (page); + _g_free0 (named_crop); + named_crop = _tmp8_; + page_get_crop (page, &_tmp9_, &_tmp10_, &_tmp11_, &_tmp12_); + cx = _tmp9_; + cy = _tmp10_; + cw = _tmp11_; + ch = _tmp12_; + } + } + _tmp13_ = book_append_page (self->priv->book, width, height, dpi, scan_direction); + _page_unref0 (page); + page = _tmp13_; + if (do_crop) { + if (named_crop != NULL) { + page_set_named_crop (page, named_crop); + } else { + page_set_custom_crop (page, cw, ch); + } + page_move_crop (page, cx, cy); + } + simple_scan_set_selected_page (self->priv->ui, page); + page_start (page); + result = page; + _g_free0 (named_crop); + return result; +} + - page = book_get_page (book, book_get_n_pages (book) - 1); - page_parse_scan_line (page, line); +static void application_scanner_new_page_cb (Application* self, Scanner* scanner) { + Page* _tmp0_ = NULL; + Page* _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + _tmp0_ = application_append_page (self); + _tmp1_ = _tmp0_; + _page_unref0 (_tmp1_); } -static void -scanner_page_done_cb (Scanner *scanner) -{ - Page *page; - page = book_get_page (book, book_get_n_pages (book) - 1); - page_finish (page); +static gchar* application_get_profile_for_device (Application* self, const gchar* device_name) { + gchar* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (device_name != NULL, NULL); + result = NULL; + return result; } -static void -remove_empty_page () -{ - Page *page; +static void application_scanner_page_info_cb (Application* self, Scanner* scanner, ScanPageInfo* info) { + Page* _tmp0_ = NULL; + Page* page; + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + g_return_if_fail (info != NULL); + g_debug ("simple-scan.vala:233: Page is %d pixels wide, %d pixels high, %d bits " \ +"per pixel", info->width, info->height, info->depth); + _tmp0_ = application_append_page (self); + page = _tmp0_; + page_set_page_info (page, info); + _tmp1_ = application_get_profile_for_device (self, info->device); + _tmp2_ = _tmp1_; + page_set_color_profile (page, _tmp2_); + _g_free0 (_tmp2_); + _page_unref0 (page); +} - page = book_get_page (book, book_get_n_pages (book) - 1); - /* Remove a failed page */ - if (page_has_data (page)) - page_finish (page); - else - book_delete_page (book, page); +static void application_scanner_line_cb (Application* self, Scanner* scanner, ScanLine* line) { + guint _tmp0_; + Page* _tmp1_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + g_return_if_fail (line != NULL); + _tmp0_ = book_get_n_pages (self->priv->book); + _tmp1_ = book_get_page (self->priv->book, ((gint) _tmp0_) - 1); + page = _tmp1_; + page_parse_scan_line (page, line); + _page_unref0 (page); } -static void -scanner_document_done_cb (Scanner *scanner) -{ - remove_empty_page (); +static void application_scanner_page_done_cb (Application* self, Scanner* scanner) { + guint _tmp0_; + Page* _tmp1_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + _tmp0_ = book_get_n_pages (self->priv->book); + _tmp1_ = book_get_page (self->priv->book, ((gint) _tmp0_) - 1); + page = _tmp1_; + page_finish (page); + _page_unref0 (page); } -static void -scanner_failed_cb (Scanner *scanner, GError *error) -{ - remove_empty_page (); - if (!g_error_matches (error, SCANNER_TYPE, SANE_STATUS_CANCELLED)) { - ui_show_error (ui, - /* Title of error dialog when scan failed */ - _("Failed to scan"), - error->message, - have_devices); - } +static void application_remove_empty_page (Application* self) { + guint _tmp0_; + Page* _tmp1_ = NULL; + Page* page; + gboolean _tmp2_; + g_return_if_fail (self != NULL); + _tmp0_ = book_get_n_pages (self->priv->book); + _tmp1_ = book_get_page (self->priv->book, ((gint) _tmp0_) - 1); + page = _tmp1_; + _tmp2_ = page_has_data (page); + if (_tmp2_) { + page_finish (page); + } else { + book_delete_page (self->priv->book, page); + } + _page_unref0 (page); } -static void -scanner_scanning_changed_cb (Scanner *scanner) -{ - ui_set_scanning (ui, scanner_is_scanning (scanner)); +static void application_scanner_document_done_cb (Application* self, Scanner* scanner) { + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + application_remove_empty_page (self); } -static void -scan_cb (SimpleScan *ui, const gchar *device, ScanOptions *options) -{ - /* Default filename to use when saving document (and extension will be added, e.g. .jpg) */ - const gchar *filename_prefix = _("Scanned Document"); - const gchar *extension; - gchar *filename; +static void application_scanner_failed_cb (Application* self, Scanner* scanner, gint error_code, const gchar* error_string) { + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + g_return_if_fail (error_string != NULL); + application_remove_empty_page (self); + if (error_code != ((gint) SANE_STATUS_CANCELLED)) { + const gchar* _tmp0_ = NULL; + _tmp0_ = _ ("Failed to scan"); + simple_scan_show_error (self->priv->ui, _tmp0_, error_string, self->priv->have_devices); + } +} - if (options->scan_mode == SCAN_MODE_COLOR) - extension = "jpg"; - else - extension = "pdf"; - g_debug ("Requesting scan at %d dpi from device '%s'", options->dpi, device); +static void application_scanner_scanning_changed_cb (Application* self, Scanner* scanner) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (scanner != NULL); + _tmp0_ = scanner_is_scanning (scanner); + simple_scan_set_scanning (self->priv->ui, _tmp0_); +} - if (!scanner_is_scanning (scanner)) - append_page (); - filename = g_strdup_printf ("%s.%s", filename_prefix, extension); - ui_set_default_file_name (ui, filename); - g_free (filename); - scanner_scan (scanner, device, options); +static void application_scan_cb (Application* self, SimpleScan* ui, const gchar* device, ScanOptions* options) { + gboolean _tmp0_; + const gchar* _tmp3_ = NULL; + gchar* _tmp4_; + gchar* filename_prefix; + gchar* extension = NULL; + gchar* _tmp7_ = NULL; + gchar* filename; + g_return_if_fail (self != NULL); + g_return_if_fail (ui != NULL); + g_return_if_fail (options != NULL); + g_debug ("simple-scan.vala:293: Requesting scan at %d dpi from device '%s'", options->dpi, device); + _tmp0_ = scanner_is_scanning (self->priv->scanner); + if (!_tmp0_) { + Page* _tmp1_ = NULL; + Page* _tmp2_; + _tmp1_ = application_append_page (self); + _tmp2_ = _tmp1_; + _page_unref0 (_tmp2_); + } + _tmp3_ = _ ("Scanned Document"); + _tmp4_ = g_strdup (_tmp3_); + filename_prefix = _tmp4_; + if (options->scan_mode == SCAN_MODE_COLOR) { + gchar* _tmp5_; + _tmp5_ = g_strdup ("jpg"); + _g_free0 (extension); + extension = _tmp5_; + } else { + gchar* _tmp6_; + _tmp6_ = g_strdup ("pdf"); + _g_free0 (extension); + extension = _tmp6_; + } + _tmp7_ = g_strdup_printf ("%s.%s", filename_prefix, extension); + filename = _tmp7_; + simple_scan_set_default_file_name (ui, filename); + scanner_scan (self->priv->scanner, device, options); + _g_free0 (filename); + _g_free0 (extension); + _g_free0 (filename_prefix); } -static void -cancel_cb (SimpleScan *ui) -{ - scanner_cancel (scanner); +static void application_cancel_cb (Application* self, SimpleScan* ui) { + g_return_if_fail (self != NULL); + g_return_if_fail (ui != NULL); + scanner_cancel (self->priv->scanner); } -static gchar * -get_temporary_filename (const gchar *prefix, const gchar *extension) -{ - gint fd; - gchar *filename, *path; - GError *error = NULL; +static gchar* application_get_temporary_filename (Application* self, const gchar* prefix, const gchar* extension) { + gchar* result = NULL; + gchar* _tmp0_ = NULL; + gchar* filename; + gchar* path = NULL; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (prefix != NULL, NULL); + g_return_val_if_fail (extension != NULL, NULL); + _tmp0_ = g_strdup_printf ("%sXXXXXX.%s", prefix, extension); + filename = _tmp0_; + { + gchar* _tmp1_ = NULL; + gint _tmp2_; + gint fd; + _tmp2_ = g_file_open_tmp (filename, &_tmp1_, &_inner_error_); + _g_free0 (path); + path = _tmp1_; + fd = _tmp2_; + if (_inner_error_ != NULL) { + goto __catch3_g_error; + } + close (fd); + } + goto __finally3; + __catch3_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("simple-scan.vala:329: Error saving email attachment: %s", e->message); + result = NULL; + _g_error_free0 (e); + _g_free0 (path); + _g_free0 (filename); + return result; + } + __finally3: + if (_inner_error_ != NULL) { + _g_free0 (path); + _g_free0 (filename); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + result = path; + _g_free0 (filename); + return result; +} + - /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and - * use the filename but it appears to work in practise */ +static void application_email_cb (Application* self, SimpleScan* ui, const gchar* profile) { + gboolean saved; + gchar* _tmp0_; + gchar* command_line; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (ui != NULL); + g_return_if_fail (profile != NULL); + saved = FALSE; + _tmp0_ = g_strdup ("xdg-email"); + command_line = _tmp0_; + if (g_strcmp0 (profile, "text") == 0) { + gchar* _tmp1_ = NULL; + gchar* path; + _tmp1_ = application_get_temporary_filename (self, "scan", "pdf"); + path = _tmp1_; + if (path != NULL) { + GFile* _tmp2_ = NULL; + GFile* file; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + gchar* _tmp5_; + _tmp2_ = g_file_new_for_path (path); + file = _tmp2_; + { + book_save (self->priv->book, "pdf", file, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch4_g_error; + } + } + goto __finally4; + __catch4_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("simple-scan.vala:355: Unable to save email file: %s", e->message); + _g_error_free0 (e); + _g_object_unref0 (file); + _g_free0 (path); + _g_free0 (command_line); + return; + } + __finally4: + if (_inner_error_ != NULL) { + _g_object_unref0 (file); + _g_free0 (path); + _g_free0 (command_line); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + _tmp3_ = g_strdup_printf (" --attach %s", path); + _tmp4_ = _tmp3_; + _tmp5_ = g_strconcat (command_line, _tmp4_, NULL); + _g_free0 (command_line); + command_line = _tmp5_; + _g_free0 (_tmp4_); + _g_object_unref0 (file); + } + _g_free0 (path); + } else { + { + gint i; + i = 0; + { + gboolean _tmp6_; + _tmp6_ = TRUE; + while (TRUE) { + guint _tmp7_; + gchar* _tmp8_ = NULL; + gchar* path; + GFile* _tmp9_ = NULL; + GFile* file; + gchar* _tmp12_ = NULL; + gchar* _tmp13_; + gchar* _tmp14_; + if (!_tmp6_) { + i++; + } + _tmp6_ = FALSE; + _tmp7_ = book_get_n_pages (self->priv->book); + if (!(((guint) i) < _tmp7_)) { + break; + } + _tmp8_ = application_get_temporary_filename (self, "scan", "jpg"); + path = _tmp8_; + if (path == NULL) { + saved = FALSE; + _g_free0 (path); + break; + } + _tmp9_ = g_file_new_for_path (path); + file = _tmp9_; + { + Page* _tmp10_ = NULL; + Page* _tmp11_; + _tmp10_ = book_get_page (self->priv->book, i); + _tmp11_ = _tmp10_; + page_save (_tmp11_, "jpeg", file, &_inner_error_); + _page_unref0 (_tmp11_); + if (_inner_error_ != NULL) { + goto __catch5_g_error; + } + } + goto __finally5; + __catch5_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("simple-scan.vala:379: Unable to save email file: %s", e->message); + _g_error_free0 (e); + _g_object_unref0 (file); + _g_free0 (path); + _g_free0 (command_line); + return; + } + __finally5: + if (_inner_error_ != NULL) { + _g_object_unref0 (file); + _g_free0 (path); + _g_free0 (command_line); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + _tmp12_ = g_strdup_printf (" --attach %s", path); + _tmp13_ = _tmp12_; + _tmp14_ = g_strconcat (command_line, _tmp13_, NULL); + _g_free0 (command_line); + command_line = _tmp14_; + _g_free0 (_tmp13_); + if (!saved) { + _g_object_unref0 (file); + _g_free0 (path); + break; + } + _g_object_unref0 (file); + _g_free0 (path); + } + } + } + } + g_debug ("simple-scan.vala:389: Launching email client: %s", command_line); + { + g_spawn_command_line_async (command_line, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch6_g_error; + } + } + goto __finally6; + __catch6_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("simple-scan.vala:396: Unable to start email: %s", e->message); + _g_error_free0 (e); + } + __finally6: + if (_inner_error_ != NULL) { + _g_free0 (command_line); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + _g_free0 (command_line); +} - filename = g_strdup_printf ("%sXXXXXX.%s", prefix, extension); - fd = g_file_open_tmp (filename, &path, &error); - g_free (filename); - if (fd < 0) { - g_warning ("Error saving email attachment: %s", error->message); - g_clear_error (&error); - return NULL; - } - close (fd); - return path; +static void application_quit_cb (Application* self, SimpleScan* ui) { + g_return_if_fail (self != NULL); + g_return_if_fail (ui != NULL); + _book_unref0 (self->priv->book); + self->priv->book = NULL; + ui = NULL; + _g_object_unref0 (self->priv->udev_client); + self->priv->udev_client = NULL; + scanner_free (self->priv->scanner); + gtk_main_quit (); } -static void -email_cb (SimpleScan *ui, const gchar *profile) -{ - gboolean saved = FALSE; - GError *error = NULL; - GString *command_line; - - command_line = g_string_new ("xdg-email"); - - /* Save text files as PDFs */ - if (strcmp (profile, "text") == 0) { - gchar *path; - - /* Open a temporary file */ - path = get_temporary_filename ("scan", "pdf"); - if (path) { - GFile *file; - - file = g_file_new_for_path (path); - saved = book_save (book, "pdf", file, &error); - g_string_append_printf (command_line, " --attach %s", path); - g_free (path); - g_object_unref (file); - } - } - else { - gint i; - - for (i = 0; i < book_get_n_pages (book); i++) { - gchar *path; - GFile *file; - - path = get_temporary_filename ("scan", "jpg"); - if (!path) { - saved = FALSE; - break; - } - - file = g_file_new_for_path (path); - saved = page_save (book_get_page (book, i), "jpeg", file, &error); - g_string_append_printf (command_line, " --attach %s", path); - g_free (path); - g_object_unref (file); - - if (!saved) - break; - } - } - - if (saved) { - g_debug ("Launchind email client: %s", command_line->str); - g_spawn_command_line_async (command_line->str, &error); - - if (error) { - g_warning ("Unable to start email: %s", error->message); - g_clear_error (&error); - } - } - else { - g_warning ("Unable to save email file: %s", error->message); - g_clear_error (&error); - } - - g_string_free (command_line, TRUE); -} - - -static void -quit_cb (SimpleScan *ui) -{ - g_object_unref (book); - g_object_unref (ui); - g_object_unref (udev_client); - scanner_free (scanner); - gtk_main_quit (); -} - - -static void -version() -{ - /* NOTE: Is not translated so can be easily parsed */ - fprintf(stderr, "%1$s %2$s\n", SIMPLE_SCAN_BINARY, VERSION); -} - - -static void -usage(int show_gtk) -{ - fprintf(stderr, - /* Description on how to use simple-scan displayed on command-line */ - _("Usage:\n" - " %s [DEVICE...] - Scanning utility"), SIMPLE_SCAN_BINARY); - - fprintf(stderr, - "\n\n"); - - fprintf(stderr, - /* Description on how to use simple-scan displayed on command-line */ - _("Help Options:\n" - " -d, --debug Print debugging messages\n" - " -v, --version Show release version\n" - " -h, --help Show help options\n" - " --help-all Show all help options\n" - " --help-gtk Show GTK+ options")); - fprintf(stderr, - "\n\n"); - - if (show_gtk) { - fprintf(stderr, - /* Description on simple-scan command-line GTK+ options displayed on command-line */ - _("GTK+ Options:\n" - " --class=CLASS Program class as used by the window manager\n" - " --name=NAME Program name as used by the window manager\n" - " --screen=SCREEN X screen to use\n" - " --sync Make X calls synchronous\n" - " --gtk-module=MODULES Load additional GTK+ modules\n" - " --g-fatal-warnings Make all warnings fatal")); - fprintf(stderr, - "\n\n"); - } -} - - -static void -log_cb (const gchar *log_domain, GLogLevelFlags log_level, - const gchar *message, gpointer data) -{ - /* Log everything to a file */ - if (log_file) { - const gchar *prefix; - - switch (log_level & G_LOG_LEVEL_MASK) { - case G_LOG_LEVEL_ERROR: - prefix = "ERROR:"; - break; - case G_LOG_LEVEL_CRITICAL: - prefix = "CRITICAL:"; - break; - case G_LOG_LEVEL_WARNING: - prefix = "WARNING:"; - break; - case G_LOG_LEVEL_MESSAGE: - prefix = "MESSAGE:"; - break; - case G_LOG_LEVEL_INFO: - prefix = "INFO:"; - break; - case G_LOG_LEVEL_DEBUG: - prefix = "DEBUG:"; - break; - default: - prefix = "LOG:"; - break; - } - - fprintf (log_file, "[%+.2fs] %s %s\n", g_timer_elapsed (log_timer, NULL), prefix, message); - } - - /* Only show debug if requested */ - if (log_level & G_LOG_LEVEL_DEBUG) { - if (debug) - g_log_default_handler (log_domain, log_level, message, data); - } - else - g_log_default_handler (log_domain, log_level, message, data); -} - - -static void -get_options (int argc, char **argv) -{ - int i; - - for (i = 1; i < argc; i++) { - char *arg = argv[i]; - - if (strcmp (arg, "-d") == 0 || - strcmp (arg, "--debug") == 0) { - debug = TRUE; - } - else if (strcmp (arg, "-v") == 0 || - strcmp (arg, "--version") == 0) { - version (); - exit (0); - } - else if (strcmp (arg, "-h") == 0 || - strcmp (arg, "--help") == 0) { - usage (FALSE); - exit (0); - } - else if (strcmp (arg, "--help-all") == 0 || - strcmp (arg, "--help-gtk") == 0) { - usage (TRUE); - exit (0); - } - else { - if (default_device) { - fprintf (stderr, "Unknown argument: '%s'\n", arg); - exit (1); - } - default_device = g_malloc0 (sizeof (ScanDevice)); - default_device->name = g_strdup (arg); - default_device->label = g_strdup (arg); - } - } -} - - -static void -on_uevent (GUdevClient *client, const gchar *action, GUdevDevice *device) -{ - scanner_redetect (scanner); -} - - -int -main (int argc, char **argv) -{ - const char *udev_subsystems[] = { "usb", NULL }; - gchar *path; - - g_thread_init (NULL); - - /* Log to a file */ - log_timer = g_timer_new (); - path = g_build_filename (g_get_user_cache_dir (), "simple-scan", NULL); - g_mkdir_with_parents (path, 0700); - g_free (path); - path = g_build_filename (g_get_user_cache_dir (), "simple-scan", "simple-scan.log", NULL); - log_file = fopen (path, "w"); - g_free (path); - g_log_set_default_handler (log_cb, NULL); - - bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - gtk_init (&argc, &argv); - - get_options (argc, argv); - - g_debug ("Starting Simple Scan %s, PID=%i", VERSION, getpid ()); - - ui = ui_new (); - book = ui_get_book (ui); - g_signal_connect (ui, "start-scan", G_CALLBACK (scan_cb), NULL); - g_signal_connect (ui, "stop-scan", G_CALLBACK (cancel_cb), NULL); - g_signal_connect (ui, "email", G_CALLBACK (email_cb), NULL); - g_signal_connect (ui, "quit", G_CALLBACK (quit_cb), NULL); - - scanner = scanner_new (); - g_signal_connect (G_OBJECT (scanner), "update-devices", G_CALLBACK (update_scan_devices_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "authorize", G_CALLBACK (authorize_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "expect-page", G_CALLBACK (scanner_new_page_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "got-page-info", G_CALLBACK (scanner_page_info_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "got-line", G_CALLBACK (scanner_line_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "page-done", G_CALLBACK (scanner_page_done_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "document-done", G_CALLBACK (scanner_document_done_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "scan-failed", G_CALLBACK (scanner_failed_cb), NULL); - g_signal_connect (G_OBJECT (scanner), "scanning-changed", G_CALLBACK (scanner_scanning_changed_cb), NULL); - - udev_client = g_udev_client_new (udev_subsystems); - g_signal_connect (udev_client, "uevent", G_CALLBACK (on_uevent), NULL); - - if (default_device) { - GList device_list; - - device_list.data = default_device; - device_list.next = NULL; - device_list.prev = NULL; - ui_set_scan_devices (ui, &device_list); - ui_set_selected_device (ui, default_device->name); - } - - ui_start (ui); - scanner_start (scanner); - - gtk_main (); - - return 0; +static void application_log_cb (const gchar* log_domain, GLogLevelFlags log_level, const gchar* message) { + g_return_if_fail (message != NULL); + if (application_log_file != NULL) { + gchar* prefix = NULL; + gdouble _tmp7_; + switch (log_level & G_LOG_LEVEL_MASK) { + case G_LOG_LEVEL_ERROR: + { + gchar* _tmp0_; + _tmp0_ = g_strdup ("ERROR:"); + _g_free0 (prefix); + prefix = _tmp0_; + break; + } + case G_LOG_LEVEL_CRITICAL: + { + gchar* _tmp1_; + _tmp1_ = g_strdup ("CRITICAL:"); + _g_free0 (prefix); + prefix = _tmp1_; + break; + } + case G_LOG_LEVEL_WARNING: + { + gchar* _tmp2_; + _tmp2_ = g_strdup ("WARNING:"); + _g_free0 (prefix); + prefix = _tmp2_; + break; + } + case G_LOG_LEVEL_MESSAGE: + { + gchar* _tmp3_; + _tmp3_ = g_strdup ("MESSAGE:"); + _g_free0 (prefix); + prefix = _tmp3_; + break; + } + case G_LOG_LEVEL_INFO: + { + gchar* _tmp4_; + _tmp4_ = g_strdup ("INFO:"); + _g_free0 (prefix); + prefix = _tmp4_; + break; + } + case G_LOG_LEVEL_DEBUG: + { + gchar* _tmp5_; + _tmp5_ = g_strdup ("DEBUG:"); + _g_free0 (prefix); + prefix = _tmp5_; + break; + } + default: + { + gchar* _tmp6_; + _tmp6_ = g_strdup ("LOG:"); + _g_free0 (prefix); + prefix = _tmp6_; + break; + } + } + _tmp7_ = g_timer_elapsed (application_log_timer, NULL); + fprintf (application_log_file, "[%+.2fs] %s %s\n", _tmp7_, prefix, message); + _g_free0 (prefix); + } + if ((log_level & G_LOG_LEVEL_DEBUG) != 0) { + if (application_debug_enabled) { + g_log_default_handler (log_domain, log_level, message, NULL); + } + } else { + g_log_default_handler (log_domain, log_level, message, NULL); + } } + + +static void application_on_uevent (Application* self, GUdevClient* client, const gchar* action, GUdevDevice* device) { + g_return_if_fail (self != NULL); + g_return_if_fail (client != NULL); + g_return_if_fail (action != NULL); + g_return_if_fail (device != NULL); + scanner_redetect (self->priv->scanner); +} + + +static void _application_log_cb_glog_func (const gchar* log_domain, GLogLevelFlags log_levels, const gchar* message, gpointer self) { + application_log_cb (log_domain, log_levels, message); +} + + +gint application_main (gchar** args, int args_length1) { + gint result = 0; + const gchar* _tmp0_ = NULL; + GOptionContext* _tmp1_ = NULL; + GOptionContext* c; + GOptionGroup* _tmp2_ = NULL; + ScanDevice* device; + GTimer* _tmp7_ = NULL; + const gchar* _tmp8_ = NULL; + gchar* _tmp9_ = NULL; + gchar* path; + const gchar* _tmp10_ = NULL; + gchar* _tmp11_ = NULL; + FILE* _tmp12_ = NULL; + pid_t _tmp13_; + Application* _tmp14_ = NULL; + Application* app; + GError * _inner_error_ = NULL; + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + gtk_init (&args_length1, &args); + _tmp0_ = _ ("[DEVICE...] - Scanning utility"); + _tmp1_ = g_option_context_new (_tmp0_); + c = _tmp1_; + g_option_context_add_main_entries (c, APPLICATION_options, GETTEXT_PACKAGE); + _tmp2_ = gtk_get_option_group (TRUE); + g_option_context_add_group (c, _tmp2_); + { + g_option_context_parse (c, &args_length1, &args, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch7_g_error; + } + } + goto __finally7; + __catch7_g_error: + { + GError* e = NULL; + const gchar* _tmp3_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + fprintf (stderr, "%s\n", e->message); + _tmp3_ = _ ("Run '%s --help' to see a full list of available command line options."); + fprintf (stderr, _tmp3_, args[0]); + fprintf (stderr, "\n"); + result = EXIT_FAILURE; + _g_error_free0 (e); + _g_option_context_free0 (c); + return result; + } + __finally7: + if (_inner_error_ != NULL) { + _g_option_context_free0 (c); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return 0; + } + if (application_show_version) { + fprintf (stderr, "simple-scan %s\n", VERSION); + result = EXIT_SUCCESS; + _g_option_context_free0 (c); + return result; + } + device = NULL; + if (args_length1 > 1) { + ScanDevice* _tmp4_ = NULL; + gchar* _tmp5_; + gchar* _tmp6_; + _tmp4_ = scan_device_new (); + _scan_device_unref0 (device); + device = _tmp4_; + _tmp5_ = g_strdup (args[1]); + _g_free0 (device->name); + device->name = _tmp5_; + _tmp6_ = g_strdup (args[1]); + _g_free0 (device->label); + device->label = _tmp6_; + } + _tmp7_ = g_timer_new (); + _g_timer_destroy0 (application_log_timer); + application_log_timer = _tmp7_; + _tmp8_ = g_get_user_cache_dir (); + _tmp9_ = g_build_filename (_tmp8_, "simple-scan", NULL, NULL); + path = _tmp9_; + g_mkdir_with_parents (path, 0700); + _tmp10_ = g_get_user_cache_dir (); + _tmp11_ = g_build_filename (_tmp10_, "simple-scan", "simple-scan.log", NULL, NULL); + _g_free0 (path); + path = _tmp11_; + _tmp12_ = fopen (path, "w"); + _fclose0 (application_log_file); + application_log_file = _tmp12_; + g_log_set_default_handler (_application_log_cb_glog_func, NULL); + _tmp13_ = getpid (); + g_debug ("simple-scan.vala:507: Starting Simple Scan %s, PID=%i", VERSION, (gint) _tmp13_); + _tmp14_ = application_new (device); + app = _tmp14_; + application_start (app); + gtk_main (); + result = EXIT_SUCCESS; + _application_unref0 (app); + _g_free0 (path); + _scan_device_unref0 (device); + _g_option_context_free0 (c); + return result; +} + + +int main (int argc, char ** argv) { + g_type_init (); + return application_main (argv, argc); +} + + +static void value_application_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_application_free_value (GValue* value) { + if (value->data[0].v_pointer) { + application_unref (value->data[0].v_pointer); + } +} + + +static void value_application_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = application_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_application_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_application_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Application* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = application_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_application_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Application** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = application_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_application (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecApplication* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_APPLICATION), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_application (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_APPLICATION), NULL); + return value->data[0].v_pointer; +} + + +void value_set_application (GValue* value, gpointer v_object) { + Application* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_APPLICATION)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_APPLICATION)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + application_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + application_unref (old); + } +} + + +void value_take_application (GValue* value, gpointer v_object) { + Application* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_APPLICATION)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_APPLICATION)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + application_unref (old); + } +} + + +static void application_class_init (ApplicationClass * klass) { + application_parent_class = g_type_class_peek_parent (klass); + APPLICATION_CLASS (klass)->finalize = application_finalize; + g_type_class_add_private (klass, sizeof (ApplicationPrivate)); +} + + +static void application_instance_init (Application * self) { + self->priv = APPLICATION_GET_PRIVATE (self); + self->priv->default_device = NULL; + self->priv->have_devices = FALSE; + self->ref_count = 1; +} + + +static void application_finalize (Application* obj) { + Application * self; + self = APPLICATION (obj); + _scan_device_unref0 (self->priv->default_device); + _g_object_unref0 (self->priv->udev_client); + _simple_scan_unref0 (self->priv->ui); + _scanner_unref0 (self->priv->scanner); + _book_unref0 (self->priv->book); +} + + +GType application_get_type (void) { + static volatile gsize application_type_id__volatile = 0; + if (g_once_init_enter (&application_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_application_init, value_application_free_value, value_application_copy_value, value_application_peek_pointer, "p", value_application_collect_value, "p", value_application_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ApplicationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) application_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Application), 0, (GInstanceInitFunc) application_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType application_type_id; + application_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Application", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&application_type_id__volatile, application_type_id); + } + return application_type_id__volatile; +} + + +gpointer application_ref (gpointer instance) { + Application* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void application_unref (gpointer instance) { + Application* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + APPLICATION_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); +} + + + diff --git a/src/simple-scan.vala b/src/simple-scan.vala new file mode 100644 index 0000000..0ced7ad --- /dev/null +++ b/src/simple-scan.vala @@ -0,0 +1,516 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public class Application +{ + static bool show_version; + static bool debug_enabled; + public static const OptionEntry[] options = + { + { "version", 'v', 0, OptionArg.NONE, ref show_version, + /* Help string for command line --version flag */ + N_("Show release version"), null}, + { "debug", 'd', 0, OptionArg.NONE, ref debug_enabled, + /* Help string for command line --debug flag */ + N_("Print debugging messages"), null}, + { null } + }; + private static Timer log_timer; + private static FileStream? log_file; + + private ScanDevice? default_device = null; + private bool have_devices = false; + private GUdev.Client udev_client; + private SimpleScan ui; + private Scanner scanner; + private Book book; + + public Application (ScanDevice? device = null) + { + default_device = device; + + ui = new SimpleScan (); + book = ui.get_book (); + ui.start_scan.connect (scan_cb); + ui.stop_scan.connect (cancel_cb); + ui.email.connect (email_cb); + ui.quit.connect (quit_cb); + + scanner = Scanner.get_instance (); + scanner.update_devices.connect (update_scan_devices_cb); + scanner.request_authorization.connect (authorize_cb); + scanner.expect_page.connect (scanner_new_page_cb); + scanner.got_page_info.connect (scanner_page_info_cb); + scanner.got_line.connect (scanner_line_cb); + scanner.page_done.connect (scanner_page_done_cb); + scanner.document_done.connect (scanner_document_done_cb); + scanner.scan_failed.connect (scanner_failed_cb); + scanner.scanning_changed.connect (scanner_scanning_changed_cb); + + string[]? subsystems = { "usb", null }; + udev_client = new GUdev.Client (subsystems); + udev_client.uevent.connect (on_uevent); + + if (default_device != null) + { + List<ScanDevice> device_list = null; + + device_list.append (default_device); + ui.set_scan_devices (device_list); + ui.set_selected_device (default_device.name); + } + } + + public void start () + { + ui.start (); + scanner.start (); + } + + private void update_scan_devices_cb (Scanner scanner, List<ScanDevice> devices) + { + var devices_copy = devices.copy (); + + /* If the default device is not detected add it to the list */ + if (default_device != null) + { + var default_in_list = false; + foreach (var device in devices_copy) + { + if (device.name == default_device.name) + { + default_in_list = true; + break; + } + } + + if (!default_in_list) + devices_copy.prepend (default_device); + } + + have_devices = devices_copy.length () > 0; + ui.set_scan_devices (devices_copy); + } + + private void authorize_cb (Scanner scanner, string resource) + { + string username, password; + ui.authorize (resource, out username, out password); + scanner.authorize (username, password); + } + + private Page append_page () + { + /* Use current page if not used */ + var page = book.get_page (-1); + if (page != null && !page.has_data ()) + { + ui.set_selected_page (page); + page.start (); + return page; + } + + /* Copy info from previous page */ + var scan_direction = ScanDirection.TOP_TO_BOTTOM; + bool do_crop = false; + string named_crop = null; + var width = 100, height = 100, dpi = 100, cx = 0, cy = 0, cw = 0, ch = 0; + if (page != null) + { + scan_direction = page.get_scan_direction (); + width = page.get_width (); + height = page.get_height (); + dpi = page.get_dpi (); + + do_crop = page.has_crop (); + if (do_crop) + { + named_crop = page.get_named_crop (); + page.get_crop (out cx, out cy, out cw, out ch); + } + } + + page = book.append_page (width, height, dpi, scan_direction); + if (do_crop) + { + if (named_crop != null) + { + page.set_named_crop (named_crop); + } + else + page.set_custom_crop (cw, ch); + page.move_crop (cx, cy); + } + ui.set_selected_page (page); + page.start (); + + return page; + } + + private void scanner_new_page_cb (Scanner scanner) + { + append_page (); + } + + private string? get_profile_for_device (string device_name) + { +#if HAVE_COLORD + var device_id = "sane:%s".printf (device_name); + debug ("Getting color profile for device %s", device_name); + + var client = new Colord.Client (); + try + { + client.connect_sync (); + } + catch (Error e) + { + debug ("Failed to connect to colord: %s", e.message); + return null; + } + + Colord.Device device; + try + { + device = client.find_device_by_property_sync (Colord.DEVICE_PROPERTY_SERIAL, device_id); + } + catch (Error e) + { + debug ("Unable to find colord device %s: %s", device_name, e.message); + return null; + } + + try + { + device.connect_sync (); + } + catch (Error e) + { + debug ("Failed to get properties from the device %s: %s", device_name, e.message); + return null; + } + + var profile = device.get_default_profile (); + if (profile == null) + { + debug ("No default color profile for device: %s", device_name); + return null; + } + + try + { + profile.connect_sync (); + } + catch (Error e) + { + debug ("Failed to get properties from the profile %s: %s", device_name, e.message); + return null; + } + + if (profile.filename == null) + { + debug ("No icc color profile for the device %s", device_name); + return null; + } + + debug ("Using color profile %s for device %s", profile.filename, device_name); + return profile.filename; +#else + return null; +#endif + } + + private void scanner_page_info_cb (Scanner scanner, ScanPageInfo info) + { + debug ("Page is %d pixels wide, %d pixels high, %d bits per pixel", + info.width, info.height, info.depth); + + /* Add a new page */ + var page = append_page (); + page.set_page_info (info); + + /* Get ICC color profile */ + /* FIXME: The ICC profile could change */ + /* FIXME: Don't do a D-bus call for each page, cache color profiles */ + page.set_color_profile (get_profile_for_device (info.device)); + } + + private void scanner_line_cb (Scanner scanner, ScanLine line) + { + var page = book.get_page ((int) book.get_n_pages () - 1); + page.parse_scan_line (line); + } + + private void scanner_page_done_cb (Scanner scanner) + { + var page = book.get_page ((int) book.get_n_pages () - 1); + page.finish (); + } + + private void remove_empty_page () + { + var page = book.get_page ((int) book.get_n_pages () - 1); + + /* Remove a failed page */ + if (page.has_data ()) + page.finish (); + else + book.delete_page (page); + } + + private void scanner_document_done_cb (Scanner scanner) + { + remove_empty_page (); + } + + private void scanner_failed_cb (Scanner scanner, int error_code, string error_string) + { + remove_empty_page (); + if (error_code != Sane.Status.CANCELLED) + { + ui.show_error (/* Title of error dialog when scan failed */ + _("Failed to scan"), + error_string, + have_devices); + } + } + + private void scanner_scanning_changed_cb (Scanner scanner) + { + ui.set_scanning (scanner.is_scanning ()); + } + + private void scan_cb (SimpleScan ui, string? device, ScanOptions options) + { + debug ("Requesting scan at %d dpi from device '%s'", options.dpi, device); + + if (!scanner.is_scanning ()) + append_page (); + + /* Default filename to use when saving document (and extension will be added, e.g. .jpg) */ + string filename_prefix = _("Scanned Document"); + string extension; + if (options.scan_mode == ScanMode.COLOR) + extension = "jpg"; + else + extension = "pdf"; + var filename = "%s.%s".printf (filename_prefix, extension); + ui.set_default_file_name (filename); + scanner.scan (device, options); + } + + private void cancel_cb (SimpleScan ui) + { + scanner.cancel (); + } + + private string? get_temporary_filename (string prefix, string extension) + { + /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and + * use the filename but it appears to work in practise */ + + var filename = "%sXXXXXX.%s".printf (prefix, extension); + string path; + try + { + var fd = FileUtils.open_tmp (filename, out path); + Posix.close (fd); + } + catch (Error e) + { + warning ("Error saving email attachment: %s", e.message); + return null; + } + + return path; + } + + private void email_cb (SimpleScan ui, string profile) + { + var saved = false; + var command_line = "xdg-email"; + + /* Save text files as PDFs */ + if (profile == "text") + { + /* Open a temporary file */ + var path = get_temporary_filename ("scan", "pdf"); + if (path != null) + { + var file = File.new_for_path (path); + try + { + book.save ("pdf", file); + } + catch (Error e) + { + warning ("Unable to save email file: %s", e.message); + return; + } + command_line += " --attach %s".printf (path); + } + } + else + { + for (var i = 0; i < book.get_n_pages (); i++) + { + var path = get_temporary_filename ("scan", "jpg"); + if (path == null) + { + saved = false; + break; + } + + var file = File.new_for_path (path); + try + { + book.get_page (i).save ("jpeg", file); + } + catch (Error e) + { + warning ("Unable to save email file: %s", e.message); + return; + } + command_line += " --attach %s".printf (path); + + if (!saved) + break; + } + } + + debug ("Launching email client: %s", command_line); + try + { + Process.spawn_command_line_async (command_line); + } + catch (Error e) + { + warning ("Unable to start email: %s", e.message); + } + } + + private void quit_cb (SimpleScan ui) + { + book = null; + ui = null; + udev_client = null; + scanner.free (); + Gtk.main_quit (); + } + + private static void log_cb (string? log_domain, LogLevelFlags log_level, string message) + { + /* Log everything to a file */ + if (log_file != null) + { + string prefix; + + switch (log_level & LogLevelFlags.LEVEL_MASK) + { + case LogLevelFlags.LEVEL_ERROR: + prefix = "ERROR:"; + break; + case LogLevelFlags.LEVEL_CRITICAL: + prefix = "CRITICAL:"; + break; + case LogLevelFlags.LEVEL_WARNING: + prefix = "WARNING:"; + break; + case LogLevelFlags.LEVEL_MESSAGE: + prefix = "MESSAGE:"; + break; + case LogLevelFlags.LEVEL_INFO: + prefix = "INFO:"; + break; + case LogLevelFlags.LEVEL_DEBUG: + prefix = "DEBUG:"; + break; + default: + prefix = "LOG:"; + break; + } + + log_file.printf ("[%+.2fs] %s %s\n", log_timer.elapsed (), prefix, message); + } + + /* Only show debug if requested */ + if ((log_level & LogLevelFlags.LEVEL_DEBUG) != 0) + { + if (debug_enabled) + Log.default_handler (log_domain, log_level, message); + } + else + Log.default_handler (log_domain, log_level, message); + } + + private void on_uevent (GUdev.Client client, string action, GUdev.Device device) + { + scanner.redetect (); + } + + public static int main (string[] args) + { + Intl.setlocale (LocaleCategory.ALL, ""); + Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALE_DIR); + Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8"); + Intl.textdomain (Config.GETTEXT_PACKAGE); + + Gtk.init (ref args); + + var c = new OptionContext (/* Arguments and description for --help text */ + _("[DEVICE...] - Scanning utility")); + c.add_main_entries (options, Config.GETTEXT_PACKAGE); + c.add_group (Gtk.get_option_group (true)); + try + { + c.parse (ref args); + } + catch (Error e) + { + stderr.printf ("%s\n", e.message); + stderr.printf (/* Text printed out when an unknown command-line argument provided */ + _("Run '%s --help' to see a full list of available command line options."), args[0]); + stderr.printf ("\n"); + return Posix.EXIT_FAILURE; + } + if (show_version) + { + /* Note, not translated so can be easily parsed */ + stderr.printf ("simple-scan %s\n", Config.VERSION); + return Posix.EXIT_SUCCESS; + } + + ScanDevice? device = null; + if (args.length > 1) + { + device = new ScanDevice (); + device.name = args[1]; + device.label = args[1]; + } + + /* Log to a file */ + log_timer = new Timer (); + var path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", null); + DirUtils.create_with_parents (path, 0700); + path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", "simple-scan.log", null); + log_file = FileStream.open (path, "w"); + Log.set_default_handler (log_cb); + + debug ("Starting Simple Scan %s, PID=%i", Config.VERSION, Posix.getpid ()); + + Application app = new Application (device); + app.start (); + + Gtk.main (); + + return Posix.EXIT_SUCCESS; + } +} diff --git a/src/simple_scan_vala.stamp b/src/simple_scan_vala.stamp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/simple_scan_vala.stamp @@ -1,7 +1,10 @@ +/* ui.c generated by valac 0.13.1, the Vala compiler + * generated from ui.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later @@ -9,1917 +12,3443 @@ * license. */ +#include <glib.h> +#include <glib-object.h> +#include <gio/gio.h> +#include <gtk/gtk.h> #include <stdlib.h> #include <string.h> -#include <glib/gi18n.h> -#include <gtk/gtk.h> -#include <gconf/gconf-client.h> +#include <glib/gi18n-lib.h> +#include <glib/gstdio.h> +#include <unistd.h> +#include <cairo.h> +#include <float.h> #include <math.h> -#include <unistd.h> // TEMP: Needed for close() in get_temporary_filename() - -#include "ui.h" -#include "book-view.h" - - -#define DEFAULT_TEXT_DPI 150 -#define DEFAULT_PHOTO_DPI 300 - - -enum { - START_SCAN, - STOP_SCAN, - EMAIL, - QUIT, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0, }; - - -struct SimpleScanPrivate -{ - GConfClient *client; - - GtkBuilder *builder; - - GtkWidget *window, *main_vbox; - GtkWidget *info_bar, *info_bar_image, *info_bar_label; - GtkWidget *info_bar_close_button, *info_bar_change_scanner_button; - GtkWidget *page_move_left_menuitem, *page_move_right_menuitem; - GtkWidget *page_delete_menuitem, *crop_rotate_menuitem; - GtkWidget *save_menuitem, *save_as_menuitem, *save_toolbutton; - GtkWidget *stop_menuitem, *stop_toolbutton; - - GtkWidget *text_toolbar_menuitem, *text_menu_menuitem; - GtkWidget *photo_toolbar_menuitem, *photo_menu_menuitem; - - GtkWidget *authorize_dialog; - GtkWidget *authorize_label; - GtkWidget *username_entry, *password_entry; - - GtkWidget *preferences_dialog; - GtkWidget *device_combo, *text_dpi_combo, *photo_dpi_combo, *page_side_combo, *paper_size_combo; - GtkTreeModel *device_model, *text_dpi_model, *photo_dpi_model, *page_side_model, *paper_size_model; - gboolean setting_devices, user_selected_device; - - gboolean have_error; - gchar *error_title, *error_text; - gboolean error_change_scanner_hint; - - Book *book; - gchar *book_uri; - - BookView *book_view; - gboolean updating_page_menu; - gint default_page_width, default_page_height, default_page_dpi; - ScanDirection default_page_scan_direction; - - gchar *document_hint; - - gchar *default_file_name; - gboolean scanning; - - gint window_width, window_height; - gboolean window_is_maximized; +#include <gdk-pixbuf/gdk-pixdata.h> +#include <gdk/gdk.h> +#include <config.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_SIMPLE_SCAN (simple_scan_get_type ()) +#define SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SIMPLE_SCAN, SimpleScan)) +#define SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SIMPLE_SCAN, SimpleScanClass)) +#define IS_SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SIMPLE_SCAN)) +#define IS_SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SIMPLE_SCAN)) +#define SIMPLE_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SIMPLE_SCAN, SimpleScanClass)) + +typedef struct _SimpleScan SimpleScan; +typedef struct _SimpleScanClass SimpleScanClass; +typedef struct _SimpleScanPrivate SimpleScanPrivate; + +#define TYPE_BOOK (book_get_type ()) +#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book)) +#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass)) +#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK)) +#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK)) +#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass)) + +typedef struct _Book Book; +typedef struct _BookClass BookClass; + +#define TYPE_BOOK_VIEW (book_view_get_type ()) +#define BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK_VIEW, BookView)) +#define BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK_VIEW, BookViewClass)) +#define IS_BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK_VIEW)) +#define IS_BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK_VIEW)) +#define BOOK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK_VIEW, BookViewClass)) + +typedef struct _BookView BookView; +typedef struct _BookViewClass BookViewClass; + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _book_unref0(var) ((var == NULL) ? NULL : (var = (book_unref (var), NULL))) + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; + +#define TYPE_SCAN_DEVICE (scan_device_get_type ()) +#define SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_DEVICE, ScanDevice)) +#define SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_DEVICE, ScanDeviceClass)) +#define IS_SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_DEVICE)) +#define IS_SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_DEVICE)) +#define SCAN_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_DEVICE, ScanDeviceClass)) + +typedef struct _ScanDevice ScanDevice; +typedef struct _ScanDeviceClass ScanDeviceClass; +typedef struct _ScanDevicePrivate ScanDevicePrivate; +#define _scan_device_unref0(var) ((var == NULL) ? NULL : (var = (scan_device_unref (var), NULL))) +#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) + +#define TYPE_SCAN_TYPE (scan_type_get_type ()) + +#define TYPE_SCAN_OPTIONS (scan_options_get_type ()) +#define SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_OPTIONS, ScanOptions)) +#define SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_OPTIONS, ScanOptionsClass)) +#define IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_OPTIONS)) +#define IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_OPTIONS)) +#define SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_OPTIONS, ScanOptionsClass)) + +typedef struct _ScanOptions ScanOptions; +typedef struct _ScanOptionsClass ScanOptionsClass; + +#define TYPE_SCAN_MODE (scan_mode_get_type ()) +typedef struct _ScanOptionsPrivate ScanOptionsPrivate; +#define _scan_options_unref0(var) ((var == NULL) ? NULL : (var = (scan_options_unref (var), NULL))) +#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL))) +typedef struct _ParamSpecSimpleScan ParamSpecSimpleScan; + +struct _SimpleScan { + GTypeInstance parent_instance; + volatile int ref_count; + SimpleScanPrivate * priv; }; -G_DEFINE_TYPE (SimpleScan, ui, G_TYPE_OBJECT); - -static struct -{ - const gchar *key; - ScanDirection scan_direction; -} scan_direction_keys[] = -{ - { "top-to-bottom", TOP_TO_BOTTOM }, - { "bottom-to-top", BOTTOM_TO_TOP }, - { "left-to-right", LEFT_TO_RIGHT }, - { "right-to-left", RIGHT_TO_LEFT }, - { NULL, 0 } +struct _SimpleScanClass { + GTypeClass parent_class; + void (*finalize) (SimpleScan *self); }; +typedef enum { + SCAN_DIRECTION_TOP_TO_BOTTOM, + SCAN_DIRECTION_LEFT_TO_RIGHT, + SCAN_DIRECTION_BOTTOM_TO_TOP, + SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _SimpleScanPrivate { + GSettings* settings; + GtkBuilder* builder; + GtkWindow* window; + GtkVBox* main_vbox; + GtkInfoBar* info_bar; + GtkImage* info_bar_image; + GtkLabel* info_bar_label; + GtkButton* info_bar_close_button; + GtkButton* info_bar_change_scanner_button; + GtkMenuItem* page_move_left_menuitem; + GtkMenuItem* page_move_right_menuitem; + GtkMenuItem* page_delete_menuitem; + GtkMenuItem* crop_rotate_menuitem; + GtkMenuItem* save_menuitem; + GtkMenuItem* save_as_menuitem; + GtkToolButton* save_toolbutton; + GtkMenuItem* stop_menuitem; + GtkToolButton* stop_toolbutton; + GtkRadioMenuItem* text_toolbar_menuitem; + GtkRadioMenuItem* text_menu_menuitem; + GtkRadioMenuItem* photo_toolbar_menuitem; + GtkRadioMenuItem* photo_menu_menuitem; + GtkDialog* authorize_dialog; + GtkLabel* authorize_label; + GtkEntry* username_entry; + GtkEntry* password_entry; + GtkDialog* preferences_dialog; + GtkComboBox* device_combo; + GtkComboBox* text_dpi_combo; + GtkComboBox* photo_dpi_combo; + GtkComboBox* page_side_combo; + GtkComboBox* paper_size_combo; + GtkListStore* device_model; + GtkListStore* text_dpi_model; + GtkListStore* photo_dpi_model; + GtkListStore* page_side_model; + GtkListStore* paper_size_model; + gboolean setting_devices; + gboolean user_selected_device; + GtkFileChooserDialog* save_dialog; + gboolean have_error; + gchar* error_title; + gchar* error_text; + gboolean error_change_scanner_hint; + Book* book; + gchar* book_uri; + BookView* book_view; + gboolean updating_page_menu; + gint default_page_width; + gint default_page_height; + gint default_page_dpi; + ScanDirection default_page_scan_direction; + gchar* document_hint; + gchar* default_file_name; + gboolean scanning; + gint window_width; + gint window_height; + gboolean window_is_maximized; +}; -static gboolean -find_scan_device (SimpleScan *ui, const char *device, GtkTreeIter *iter) -{ - gboolean have_iter = FALSE; - - if (gtk_tree_model_get_iter_first (ui->priv->device_model, iter)) { - do { - gchar *d; - gtk_tree_model_get (ui->priv->device_model, iter, 0, &d, -1); - if (strcmp (d, device) == 0) - have_iter = TRUE; - g_free (d); - } while (!have_iter && gtk_tree_model_iter_next (ui->priv->device_model, iter)); - } - - return have_iter; -} - - -static void -show_error_dialog (SimpleScan *ui, const char *error_title, const char *error_text) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (ui->priv->window), - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - "%s", error_title); - gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, 0); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error_text); - gtk_widget_destroy (dialog); -} - - -void -ui_set_default_file_name (SimpleScan *ui, const gchar *default_file_name) -{ - g_free (ui->priv->default_file_name); - ui->priv->default_file_name = g_strdup (default_file_name); -} - - -void -ui_authorize (SimpleScan *ui, const gchar *resource, gchar **username, gchar **password) -{ - GString *description; - - description = g_string_new (""); - g_string_printf (description, - /* Label in authorization dialog. '%s' is replaced with the name of the resource requesting authorization */ - _("Username and password required to access '%s'"), - resource); - - gtk_entry_set_text (GTK_ENTRY (ui->priv->username_entry), *username ? *username : ""); - gtk_entry_set_text (GTK_ENTRY (ui->priv->password_entry), ""); - gtk_label_set_text (GTK_LABEL (ui->priv->authorize_label), description->str); - g_string_free (description, TRUE); - - gtk_widget_show (ui->priv->authorize_dialog); - gtk_dialog_run (GTK_DIALOG (ui->priv->authorize_dialog)); - gtk_widget_hide (ui->priv->authorize_dialog); - - *username = g_strdup (gtk_entry_get_text (GTK_ENTRY (ui->priv->username_entry))); - *password = g_strdup (gtk_entry_get_text (GTK_ENTRY (ui->priv->password_entry))); -} - - -void device_combo_changed_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -device_combo_changed_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (ui->priv->setting_devices) - return; - ui->priv->user_selected_device = TRUE; -} - - -static void -update_info_bar (SimpleScan *ui) -{ - GtkMessageType type; - const gchar *title, *text, *image_id; - gchar *message; - gboolean show_close_button = FALSE; - gboolean show_change_scanner_button = FALSE; - - if (ui->priv->have_error) { - type = GTK_MESSAGE_ERROR; - image_id = GTK_STOCK_DIALOG_ERROR; - title = ui->priv->error_title; - text = ui->priv->error_text; - show_close_button = TRUE; - show_change_scanner_button = ui->priv->error_change_scanner_hint; - } - else if (gtk_tree_model_iter_n_children (ui->priv->device_model, NULL) == 0) { - type = GTK_MESSAGE_WARNING; - image_id = GTK_STOCK_DIALOG_WARNING; - /* Warning displayed when no scanners are detected */ - title = _("No scanners detected"); - /* Hint to user on why there are no scanners detected */ - text = _("Please check your scanner is connected and powered on"); - } - else { - gtk_widget_hide (ui->priv->info_bar); - return; - } - - gtk_info_bar_set_message_type (GTK_INFO_BAR (ui->priv->info_bar), type); - gtk_image_set_from_stock (GTK_IMAGE (ui->priv->info_bar_image), image_id, GTK_ICON_SIZE_DIALOG); - message = g_strdup_printf ("<big><b>%s</b></big>\n\n%s", title, text); - gtk_label_set_markup (GTK_LABEL (ui->priv->info_bar_label), message); - g_free (message); - gtk_widget_set_visible (ui->priv->info_bar_close_button, show_close_button); - gtk_widget_set_visible (ui->priv->info_bar_change_scanner_button, show_change_scanner_button); - gtk_widget_show (ui->priv->info_bar); -} - - -void -ui_set_scan_devices (SimpleScan *ui, GList *devices) -{ - GList *d; - gboolean have_selection = FALSE; - gint index; - GtkTreeIter iter; - - ui->priv->setting_devices = TRUE; - - /* If the user hasn't chosen a scanner choose the best available one */ - if (ui->priv->user_selected_device) - have_selection = gtk_combo_box_get_active (GTK_COMBO_BOX (ui->priv->device_combo)) >= 0; - - /* Add new devices */ - index = 0; - for (d = devices; d; d = d->next) { - ScanDevice *device = (ScanDevice *) d->data; - gint n_delete = -1; - - /* Find if already exists */ - if (gtk_tree_model_iter_nth_child (ui->priv->device_model, &iter, NULL, index)) { - gint i = 0; - do { - gchar *name; - gboolean matched; - - gtk_tree_model_get (ui->priv->device_model, &iter, 0, &name, -1); - matched = strcmp (name, device->name) == 0; - g_free (name); - - if (matched) { - n_delete = i; - break; - } - i++; - } while (gtk_tree_model_iter_next (ui->priv->device_model, &iter)); - } - - /* If exists, remove elements up to this one */ - if (n_delete >= 0) { - gint i; - - /* Update label */ - gtk_list_store_set (GTK_LIST_STORE (ui->priv->device_model), &iter, 1, device->label, -1); - - for (i = 0; i < n_delete; i++) { - gtk_tree_model_iter_nth_child (ui->priv->device_model, &iter, NULL, index); - gtk_list_store_remove (GTK_LIST_STORE (ui->priv->device_model), &iter); - } - } - else { - gtk_list_store_insert (GTK_LIST_STORE (ui->priv->device_model), &iter, index); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->device_model), &iter, 0, device->name, 1, device->label, -1); - } - index++; - } - - /* Remove any remaining devices */ - while (gtk_tree_model_iter_nth_child (ui->priv->device_model, &iter, NULL, index)) - gtk_list_store_remove (GTK_LIST_STORE (ui->priv->device_model), &iter); - - /* Select the first available device */ - if (!have_selection && devices != NULL) - gtk_combo_box_set_active (GTK_COMBO_BOX (ui->priv->device_combo), 0); - - ui->priv->setting_devices = FALSE; - - update_info_bar (ui); -} - - -static gchar * -get_selected_device (SimpleScan *ui) -{ - GtkTreeIter iter; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->device_combo), &iter)) { - gchar *device; - gtk_tree_model_get (ui->priv->device_model, &iter, 0, &device, -1); - return device; - } - - return NULL; -} - - -void -ui_set_selected_device (SimpleScan *ui, const gchar *device) -{ - GtkTreeIter iter; - - if (!find_scan_device (ui, device, &iter)) - return; - - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->device_combo), &iter); - ui->priv->user_selected_device = TRUE; -} - - -static void -add_default_page (SimpleScan *ui) -{ - Page *page; - - page = book_append_page (ui->priv->book, - ui->priv->default_page_width, - ui->priv->default_page_height, - ui->priv->default_page_dpi, - ui->priv->default_page_scan_direction); - book_view_select_page (ui->priv->book_view, page); -} - - -static void -on_file_type_changed (GtkTreeSelection *selection, GtkWidget *dialog) -{ - GtkTreeModel *model; - GtkTreeIter iter; - gchar *path, *filename, *extension, *new_filename; - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, 1, &extension, -1); - path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - filename = g_path_get_basename (path); - - /* Replace extension */ - if (g_strrstr (filename, ".")) - new_filename = g_strdup_printf ("%.*s%s", (int)(g_strrstr (filename, ".") - filename), filename, extension); - else - new_filename = g_strdup_printf ("%s%s", filename, extension); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), new_filename); - - g_free (path); - g_free (filename); - g_free (new_filename); - g_free (extension); -} - - -static gchar * -choose_file_location (SimpleScan *ui) -{ - GtkWidget *dialog; - gint response; - GtkFileFilter *filter; - GtkWidget *expander, *file_type_view; - GtkListStore *file_type_store; - GtkTreeIter iter; - GtkTreeViewColumn *column; - const gchar *extension; - gchar *directory, *uri = NULL; - gint i; - - struct - { - gchar *label, *extension; - } file_types[] = - { - /* Save dialog: Label for saving in PDF format */ - { _("PDF (multi-page document)"), ".pdf" }, - /* Save dialog: Label for saving in JPEG format */ - { _("JPEG (compressed)"), ".jpg" }, - /* Save dialog: Label for saving in PNG format */ - { _("PNG (lossless)"), ".png" }, - { NULL, NULL } - }; - - /* Get directory to save to */ - directory = gconf_client_get_string (ui->priv->client, GCONF_DIR "/save_directory", NULL); - if (!directory || directory[0] == '\0') { - g_free (directory); - directory = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS)); - } - - dialog = gtk_file_chooser_dialog_new (/* Save dialog: Dialog title */ - _("Save As..."), - GTK_WINDOW (ui->priv->window), - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); - gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE); - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), directory); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), ui->priv->default_file_name); - g_free (directory); - - /* Filter to only show images by default */ - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, - /* Save dialog: Filter name to show only image files */ - _("Image Files")); - gtk_file_filter_add_pixbuf_formats (filter); - gtk_file_filter_add_mime_type (filter, "application/pdf"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, - /* Save dialog: Filter name to show all files */ - _("All Files")); - gtk_file_filter_add_pattern (filter, "*"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - expander = gtk_expander_new_with_mnemonic (/* */ - _("Select File _Type")); - gtk_expander_set_spacing (GTK_EXPANDER (expander), 5); - gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), expander); - - extension = strstr (ui->priv->default_file_name, "."); - if (!extension) - extension = ""; - - file_type_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - for (i = 0; file_types[i].label; i++) { - gtk_list_store_append (file_type_store, &iter); - gtk_list_store_set (file_type_store, &iter, 0, file_types[i].label, 1, file_types[i].extension, -1); - } - - file_type_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file_type_store)); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (file_type_view), FALSE); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (file_type_view), TRUE); - column = gtk_tree_view_column_new_with_attributes ("", - gtk_cell_renderer_text_new (), - "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (file_type_view), column); - gtk_container_add (GTK_CONTAINER (expander), file_type_view); - - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (file_type_store), &iter)) { - do { - gchar *e; - gtk_tree_model_get (GTK_TREE_MODEL (file_type_store), &iter, 1, &e, -1); - if (strcmp (extension, e) == 0) - gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (file_type_view)), &iter); - g_free (e); - } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (file_type_store), &iter)); - } - g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (file_type_view)), - "changed", - G_CALLBACK (on_file_type_changed), - dialog); - - gtk_widget_show_all (expander); - - response = gtk_dialog_run (GTK_DIALOG (dialog)); - - if (response == GTK_RESPONSE_ACCEPT) - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); - - gconf_client_set_string (ui->priv->client, GCONF_DIR "/save_directory", - gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)), - NULL); - - gtk_widget_destroy (dialog); - - return uri; -} - - -static gboolean -save_document (SimpleScan *ui, gboolean force_choose_location) -{ - gboolean result; - gchar *uri, *uri_lower; - GError *error = NULL; - GFile *file; - - if (ui->priv->book_uri && !force_choose_location) - uri = g_strdup (ui->priv->book_uri); - else - uri = choose_file_location (ui); - if (!uri) - return FALSE; - - file = g_file_new_for_uri (uri); - - g_debug ("Saving to '%s'", uri); - - uri_lower = g_utf8_strdown (uri, -1); - if (g_str_has_suffix (uri_lower, ".pdf")) - result = book_save (ui->priv->book, "pdf", file, &error); - else if (g_str_has_suffix (uri_lower, ".ps")) - result = book_save (ui->priv->book, "ps", file, &error); - else if (g_str_has_suffix (uri_lower, ".png")) - result = book_save (ui->priv->book, "png", file, &error); - else if (g_str_has_suffix (uri_lower, ".tif") || g_str_has_suffix (uri_lower, ".tiff")) - result = book_save (ui->priv->book, "tiff", file, &error); - else - result = book_save (ui->priv->book, "jpeg", file, &error); - - g_free (uri_lower); - - if (result) { - g_free (ui->priv->book_uri); - ui->priv->book_uri = uri; - book_set_needs_saving (ui->priv->book, FALSE); - } - else { - g_free (uri); - - g_warning ("Error saving file: %s", error->message); - ui_show_error (ui, - /* Title of error dialog when save failed */ - _("Failed to save file"), - error->message, - FALSE); - g_clear_error (&error); - } - - g_object_unref (file); - - return result; -} - - -static gboolean -prompt_to_save (SimpleScan *ui, const gchar *title, const gchar *discard_label) -{ - GtkWidget *dialog; - gint response; - - if (!book_get_needs_saving (ui->priv->book)) - return TRUE; - - dialog = gtk_message_dialog_new (GTK_WINDOW (ui->priv->window), - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - "%s", title); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", - /* Text in dialog warning when a document is about to be lost*/ - _("If you don't save, changes will be permanently lost.")); - gtk_dialog_add_button (GTK_DIALOG (dialog), discard_label, GTK_RESPONSE_NO); - gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_SAVE, GTK_RESPONSE_YES); - - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - switch (response) { - case GTK_RESPONSE_YES: - if (save_document (ui, FALSE)) - return TRUE; - else - return FALSE; - case GTK_RESPONSE_CANCEL: - return FALSE; - case GTK_RESPONSE_NO: - default: - return TRUE; - } -} - - -static void -clear_document (SimpleScan *ui) -{ - book_clear (ui->priv->book); - add_default_page (ui); - g_free (ui->priv->book_uri); - ui->priv->book_uri = NULL; - book_set_needs_saving (ui->priv->book, FALSE); - gtk_widget_set_sensitive (ui->priv->save_as_menuitem, FALSE); -} - - -void new_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -new_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (!prompt_to_save (ui, - /* Text in dialog warning when a document is about to be lost */ - _("Save current document?"), - /* Button in dialog to create new document and discard unsaved document */ - _("Discard Changes"))) - return; - - clear_document (ui); -} - - -static void -set_document_hint (SimpleScan *ui, const gchar *document_hint) -{ - g_free (ui->priv->document_hint); - ui->priv->document_hint = g_strdup (document_hint); - - if (strcmp (document_hint, "text") == 0) { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->text_toolbar_menuitem), TRUE); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->text_menu_menuitem), TRUE); - } - else if (strcmp (document_hint, "photo") == 0) { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->photo_toolbar_menuitem), TRUE); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->photo_menu_menuitem), TRUE); - } -} - - -void text_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -text_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_document_hint (ui, "text"); -} - - -void photo_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -photo_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_document_hint (ui, "photo"); -} - - -static void -set_page_side (SimpleScan *ui, const gchar *document_hint) -{ - GtkTreeIter iter; - - if (gtk_tree_model_get_iter_first (ui->priv->page_side_model, &iter)) { - do { - gchar *d; - gboolean have_match; - - gtk_tree_model_get (ui->priv->page_side_model, &iter, 0, &d, -1); - have_match = strcmp (d, document_hint) == 0; - g_free (d); - - if (have_match) { - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->page_side_combo), &iter); - return; - } - } while (gtk_tree_model_iter_next (ui->priv->page_side_model, &iter)); - } -} - - -static void -set_paper_size (SimpleScan *ui, gint width, gint height) -{ - GtkTreeIter iter; - gboolean have_iter; - - for (have_iter = gtk_tree_model_get_iter_first (ui->priv->paper_size_model, &iter); - have_iter; - have_iter = gtk_tree_model_iter_next (ui->priv->paper_size_model, &iter)) { - gint w, h; - - gtk_tree_model_get (ui->priv->paper_size_model, &iter, 0, &w, 1, &h, -1); - if (w == width && h == height) - break; - } - - if (!have_iter) - have_iter = gtk_tree_model_get_iter_first (ui->priv->paper_size_model, &iter); - if (have_iter) - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->paper_size_combo), &iter); -} - - -static gint -get_text_dpi (SimpleScan *ui) -{ - GtkTreeIter iter; - gint dpi = DEFAULT_TEXT_DPI; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->text_dpi_combo), &iter)) - gtk_tree_model_get (ui->priv->text_dpi_model, &iter, 0, &dpi, -1); - - return dpi; -} - - -static gint -get_photo_dpi (SimpleScan *ui) -{ - GtkTreeIter iter; - gint dpi = DEFAULT_PHOTO_DPI; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->photo_dpi_combo), &iter)) - gtk_tree_model_get (ui->priv->photo_dpi_model, &iter, 0, &dpi, -1); - - return dpi; -} - - -static gchar * -get_page_side (SimpleScan *ui) -{ - GtkTreeIter iter; - gchar *mode = NULL; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->page_side_combo), &iter)) - gtk_tree_model_get (ui->priv->page_side_model, &iter, 0, &mode, -1); - - return mode; -} - - -static gboolean -get_paper_size (SimpleScan *ui, gint *width, gint *height) -{ - GtkTreeIter iter; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->paper_size_combo), &iter)) { - gtk_tree_model_get (ui->priv->paper_size_model, &iter, 0, width, 1, height, -1); - return TRUE; - } - - return FALSE; -} - - -static ScanOptions * -get_scan_options (SimpleScan *ui) -{ - struct { - const gchar *name; - ScanMode mode; - gint depth; - } profiles[] = - { - { "text", SCAN_MODE_GRAY, 2 }, - { "photo", SCAN_MODE_COLOR, 8 }, - { NULL, SCAN_MODE_COLOR, 8 } - }; - gint i; - ScanOptions *options; - - /* Find this profile */ - // FIXME: Move this into scan-profile.c - for (i = 0; profiles[i].name && strcmp (profiles[i].name, ui->priv->document_hint) != 0; i++); - - options = g_malloc0 (sizeof (ScanOptions)); - options->scan_mode = profiles[i].mode; - options->depth = profiles[i].depth; - if (options->scan_mode == SCAN_MODE_COLOR) - options->dpi = get_photo_dpi (ui); - else - options->dpi = get_text_dpi (ui); - get_paper_size (ui, &options->paper_width, &options->paper_height); - - return options; -} - - -void scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - gchar *device; - ScanOptions *options; - - device = get_selected_device (ui); - - options = get_scan_options (ui); - options->type = SCAN_SINGLE; - g_signal_emit (G_OBJECT (ui), signals[START_SCAN], 0, device, options); - g_free (device); - g_free (options); -} - - -void stop_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -stop_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - g_signal_emit (G_OBJECT (ui), signals[STOP_SCAN], 0); -} - - -void continuous_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -continuous_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (ui->priv->scanning) { - g_signal_emit (G_OBJECT (ui), signals[STOP_SCAN], 0); - } else { - gchar *device, *side; - ScanOptions *options; - - device = get_selected_device (ui); - options = get_scan_options (ui); - side = get_page_side (ui); - if (strcmp (side, "front") == 0) - options->type = SCAN_ADF_FRONT; - else if (strcmp (side, "back") == 0) - options->type = SCAN_ADF_BACK; - else - options->type = SCAN_ADF_BOTH; - - g_signal_emit (G_OBJECT (ui), signals[START_SCAN], 0, device, options); - g_free (device); - g_free (side); - g_free (options); - } -} - - -void preferences_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -preferences_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - gtk_window_present (GTK_WINDOW (ui->priv->preferences_dialog)); -} - - -gboolean preferences_dialog_delete_event_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -gboolean -preferences_dialog_delete_event_cb (GtkWidget *widget, SimpleScan *ui) -{ - return TRUE; -} - - -void preferences_dialog_response_cb (GtkWidget *widget, gint response_id, SimpleScan *ui); -G_MODULE_EXPORT -void -preferences_dialog_response_cb (GtkWidget *widget, gint response_id, SimpleScan *ui) -{ - gtk_widget_hide (ui->priv->preferences_dialog); -} - - -static void -update_page_menu (SimpleScan *ui) -{ - Book *book; - gint index; - - book = book_view_get_book (ui->priv->book_view); - index = book_get_page_index (book, book_view_get_selected (ui->priv->book_view)); - gtk_widget_set_sensitive (ui->priv->page_move_left_menuitem, index > 0); - gtk_widget_set_sensitive (ui->priv->page_move_right_menuitem, index < book_get_n_pages (book) - 1); -} - - -static void -page_selected_cb (BookView *view, Page *page, SimpleScan *ui) -{ - char *name = NULL; - - if (page == NULL) - return; - - ui->priv->updating_page_menu = TRUE; - - update_page_menu (ui); - - if (page_has_crop (page)) { - char *crop_name; - - // FIXME: Make more generic, move into page-size.c and reuse - crop_name = page_get_named_crop (page); - if (crop_name) { - if (strcmp (crop_name, "A4") == 0) - name = "a4_menuitem"; - else if (strcmp (crop_name, "A5") == 0) - name = "a5_menuitem"; - else if (strcmp (crop_name, "A6") == 0) - name = "a6_menuitem"; - else if (strcmp (crop_name, "letter") == 0) - name = "letter_menuitem"; - else if (strcmp (crop_name, "legal") == 0) - name = "legal_menuitem"; - else if (strcmp (crop_name, "4x6") == 0) - name = "4x6_menuitem"; - g_free (crop_name); - } - else - name = "custom_crop_menuitem"; - } - else - name = "no_crop_menuitem"; - - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (ui->priv->builder, name)), TRUE); - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (gtk_builder_get_object (ui->priv->builder, "crop_toolbutton")), page_has_crop (page)); - - ui->priv->updating_page_menu = FALSE; -} - - -// FIXME: Duplicated from simple-scan.c -static gchar * -get_temporary_filename (const gchar *prefix, const gchar *extension) -{ - gint fd; - gchar *filename, *path; - GError *error = NULL; - - /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and - * use the filename but it appears to work in practise */ - - filename = g_strdup_printf ("%s-XXXXXX.%s", prefix, extension); - fd = g_file_open_tmp (filename, &path, &error); - g_free (filename); - if (fd < 0) { - g_warning ("Error saving page for viewing: %s", error->message); - g_clear_error (&error); - return NULL; - } - close (fd); - - return path; -} - - -static void -show_page_cb (BookView *view, Page *page, SimpleScan *ui) -{ - gchar *path; - GFile *file; - GdkScreen *screen; - GError *error = NULL; - - path = get_temporary_filename ("scanned-page", "tiff"); - if (!path) - return; - file = g_file_new_for_path (path); - g_free (path); - - screen = gtk_widget_get_screen (GTK_WIDGET (ui->priv->window)); - - if (page_save (page, "tiff", file, &error)) { - gchar *uri = g_file_get_uri (file); - gtk_show_uri (screen, uri, gtk_get_current_event_time (), &error); - g_free (uri); - } - - g_object_unref (file); - - if (error) { - show_error_dialog (ui, - /* Error message display when unable to preview image */ - _("Unable to open image preview application"), - error->message); - g_clear_error (&error); - } -} - - -static void -show_page_menu_cb (BookView *view, SimpleScan *ui) -{ - gtk_menu_popup (GTK_MENU (gtk_builder_get_object (ui->priv->builder, "page_menu")), NULL, NULL, NULL, NULL, - 3, gtk_get_current_event_time()); -} - - -void rotate_left_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -rotate_left_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - Page *page; - - if (ui->priv->updating_page_menu) - return; - page = book_view_get_selected (ui->priv->book_view); - page_rotate_left (page); -} - - -void rotate_right_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -rotate_right_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - Page *page; - - if (ui->priv->updating_page_menu) - return; - page = book_view_get_selected (ui->priv->book_view); - page_rotate_right (page); -} - - -static void -set_crop (SimpleScan *ui, const gchar *crop_name) -{ - Page *page; - - gtk_widget_set_sensitive (ui->priv->crop_rotate_menuitem, crop_name != NULL); - - if (ui->priv->updating_page_menu) - return; - - page = book_view_get_selected (ui->priv->book_view); - if (!page) - return; - - if (!crop_name) { - page_set_no_crop (page); - return; - } - - if (strcmp (crop_name, "custom") == 0) { - gint width, height, crop_width, crop_height; - - width = page_get_width (page); - height = page_get_height (page); - - crop_width = (int) (width * 0.8 + 0.5); - crop_height = (int) (height * 0.8 + 0.5); - page_set_custom_crop (page, crop_width, crop_height); - page_move_crop (page, (width - crop_width) / 2, (height - crop_height) / 2); - - return; - } - - page_set_named_crop (page, crop_name); -} - - -void no_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -no_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, NULL); -} - - -void custom_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -custom_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "custom"); -} - -void crop_toolbutton_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -crop_toolbutton_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (ui->priv->updating_page_menu) - return; - - if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget))) - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (ui->priv->builder, "custom_crop_menuitem")), TRUE); - else - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (ui->priv->builder, "no_crop_menuitem")), TRUE); -} - - -void four_by_six_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -four_by_six_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "4x6"); -} - - -void legal_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -legal_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "legal"); -} - - -void letter_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -letter_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "letter"); -} - - -void a6_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -a6_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "A6"); -} - - -void a5_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -a5_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "A5"); -} +struct _ScanDevice { + GTypeInstance parent_instance; + volatile int ref_count; + ScanDevicePrivate * priv; + gchar* name; + gchar* label; +}; - -void a4_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -a4_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui) -{ - if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) - set_crop (ui, "A4"); -} +struct _ScanDeviceClass { + GTypeClass parent_class; + void (*finalize) (ScanDevice *self); +}; +typedef enum { + SCAN_TYPE_SINGLE, + SCAN_TYPE_ADF_FRONT, + SCAN_TYPE_ADF_BACK, + SCAN_TYPE_ADF_BOTH +} ScanType; + +typedef enum { + SCAN_MODE_DEFAULT, + SCAN_MODE_COLOR, + SCAN_MODE_GRAY, + SCAN_MODE_LINEART +} ScanMode; + +struct _ScanOptions { + GTypeInstance parent_instance; + volatile int ref_count; + ScanOptionsPrivate * priv; + gint dpi; + ScanMode scan_mode; + gint depth; + ScanType type; + gint paper_width; + gint paper_height; +}; -void crop_rotate_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -crop_rotate_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - Page *page; - - page = book_view_get_selected (ui->priv->book_view); - if (!page) - return; - - page_rotate_crop (page); -} +struct _ScanOptionsClass { + GTypeClass parent_class; + void (*finalize) (ScanOptions *self); +}; +struct _ParamSpecSimpleScan { + GParamSpec parent_instance; +}; -void page_move_left_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -page_move_left_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - Book *book = book_view_get_book (ui->priv->book_view); - Page *page = book_view_get_selected (ui->priv->book_view); - gint index; - index = book_get_page_index (book, page); - if (index > 0) - book_move_page (book, page, index - 1); +static gpointer simple_scan_parent_class = NULL; + +gpointer simple_scan_ref (gpointer instance); +void simple_scan_unref (gpointer instance); +GParamSpec* param_spec_simple_scan (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_simple_scan (GValue* value, gpointer v_object); +void value_take_simple_scan (GValue* value, gpointer v_object); +gpointer value_get_simple_scan (const GValue* value); +GType simple_scan_get_type (void) G_GNUC_CONST; +gpointer book_ref (gpointer instance); +void book_unref (gpointer instance); +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_book (GValue* value, gpointer v_object); +void value_take_book (GValue* value, gpointer v_object); +gpointer value_get_book (const GValue* value); +GType book_get_type (void) G_GNUC_CONST; +GType book_view_get_type (void) G_GNUC_CONST; +GType scan_direction_get_type (void) G_GNUC_CONST; +#define SIMPLE_SCAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_SIMPLE_SCAN, SimpleScanPrivate)) +enum { + SIMPLE_SCAN_DUMMY_PROPERTY +}; +#define SIMPLE_SCAN_DEFAULT_TEXT_DPI 150 +#define SIMPLE_SCAN_DEFAULT_PHOTO_DPI 300 +SimpleScan* simple_scan_new (void); +SimpleScan* simple_scan_construct (GType object_type); +Book* book_new (void); +Book* book_construct (GType object_type); +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +static void simple_scan_page_removed_cb (SimpleScan* self, Book* book, Page* page); +static void _simple_scan_page_removed_cb_book_page_removed (Book* _sender, Page* page, gpointer self); +static void simple_scan_page_added_cb (SimpleScan* self, Book* book, Page* page); +static void _simple_scan_page_added_cb_book_page_added (Book* _sender, Page* page, gpointer self); +static void simple_scan_load (SimpleScan* self); +static gboolean simple_scan_find_scan_device (SimpleScan* self, const gchar* device, GtkTreeIter* iter); +static void simple_scan_show_error_dialog (SimpleScan* self, const gchar* error_title, const gchar* error_text); +void simple_scan_set_default_file_name (SimpleScan* self, const gchar* default_file_name); +void simple_scan_authorize (SimpleScan* self, const gchar* resource, gchar** username, gchar** password); +void G_MODULE_EXPORT device_combo_changed_cb (GtkWidget* widget, SimpleScan* self); +static void simple_scan_update_info_bar (SimpleScan* self); +gpointer scan_device_ref (gpointer instance); +void scan_device_unref (gpointer instance); +GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_device (GValue* value, gpointer v_object); +void value_take_scan_device (GValue* value, gpointer v_object); +gpointer value_get_scan_device (const GValue* value); +GType scan_device_get_type (void) G_GNUC_CONST; +void simple_scan_set_scan_devices (SimpleScan* self, GList* devices); +static gchar* simple_scan_get_selected_device (SimpleScan* self); +void simple_scan_set_selected_device (SimpleScan* self, const gchar* device); +static void simple_scan_add_default_page (SimpleScan* self); +Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction); +void book_view_select_page (BookView* self, Page* page); +static void simple_scan_on_file_type_changed (SimpleScan* self, GtkTreeSelection* selection); +static gchar* simple_scan_choose_file_location (SimpleScan* self); +static void _simple_scan_on_file_type_changed_gtk_tree_selection_changed (GtkTreeSelection* _sender, gpointer self); +static gboolean simple_scan_save_document (SimpleScan* self, gboolean force_choose_location); +void book_save (Book* self, const gchar* type, GFile* file, GError** error); +void simple_scan_show_error (SimpleScan* self, const gchar* error_title, const gchar* error_text, gboolean change_scanner_hint); +void book_set_needs_saving (Book* self, gboolean needs_saving); +static gboolean simple_scan_prompt_to_save (SimpleScan* self, const gchar* title, const gchar* discard_label); +gboolean book_get_needs_saving (Book* self); +static void simple_scan_clear_document (SimpleScan* self); +void book_clear (Book* self); +void G_MODULE_EXPORT new_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +static void simple_scan_set_document_hint (SimpleScan* self, const gchar* document_hint); +void G_MODULE_EXPORT text_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT photo_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +GType scan_type_get_type (void) G_GNUC_CONST; +static void simple_scan_set_page_side (SimpleScan* self, ScanType page_side); +static void simple_scan_set_paper_size (SimpleScan* self, gint width, gint height); +static gint simple_scan_get_text_dpi (SimpleScan* self); +static gint simple_scan_get_photo_dpi (SimpleScan* self); +static ScanType simple_scan_get_page_side (SimpleScan* self); +static gboolean simple_scan_get_paper_size (SimpleScan* self, gint* width, gint* height); +gpointer scan_options_ref (gpointer instance); +void scan_options_unref (gpointer instance); +GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_options (GValue* value, gpointer v_object); +void value_take_scan_options (GValue* value, gpointer v_object); +gpointer value_get_scan_options (const GValue* value); +GType scan_options_get_type (void) G_GNUC_CONST; +static ScanOptions* simple_scan_get_scan_options (SimpleScan* self); +ScanOptions* scan_options_new (void); +ScanOptions* scan_options_construct (GType object_type); +GType scan_mode_get_type (void) G_GNUC_CONST; +void G_MODULE_EXPORT scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT stop_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT continuous_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT preferences_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +gboolean G_MODULE_EXPORT preferences_dialog_delete_event_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT preferences_dialog_response_cb (GtkWidget* widget, gint response_id, SimpleScan* self); +static void simple_scan_update_page_menu (SimpleScan* self); +Page* book_view_get_selected (BookView* self); +guint book_get_page_index (Book* self, Page* page); +guint book_get_n_pages (Book* self); +static void simple_scan_page_selected_cb (SimpleScan* self, BookView* view, Page* page); +gboolean page_has_crop (Page* self); +gchar* page_get_named_crop (Page* self); +static gchar* simple_scan_get_temporary_filename (SimpleScan* self, const gchar* prefix, const gchar* extension); +static void simple_scan_show_page_cb (SimpleScan* self, BookView* view, Page* page); +void page_save (Page* self, const gchar* type, GFile* file, GError** error); +static void simple_scan_show_page_menu_cb (SimpleScan* self, BookView* view); +void G_MODULE_EXPORT rotate_left_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void page_rotate_left (Page* self); +void G_MODULE_EXPORT rotate_right_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void page_rotate_right (Page* self); +static void simple_scan_set_crop (SimpleScan* self, const gchar* crop_name); +void page_set_no_crop (Page* self); +gint page_get_width (Page* self); +gint page_get_height (Page* self); +void page_set_custom_crop (Page* self, gint width, gint height); +void page_move_crop (Page* self, gint x, gint y); +void page_set_named_crop (Page* self, const gchar* name); +void G_MODULE_EXPORT no_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT custom_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT crop_toolbutton_toggled_cb (GtkToggleToolButton* widget, SimpleScan* self); +void G_MODULE_EXPORT four_by_six_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT legal_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT letter_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT a6_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT a5_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT a4_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self); +void G_MODULE_EXPORT crop_rotate_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +void page_rotate_crop (Page* self); +void G_MODULE_EXPORT page_move_left_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +void book_move_page (Book* self, Page* page, guint location); +void G_MODULE_EXPORT page_move_right_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT page_delete_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +Book* book_view_get_book (BookView* self); +void book_delete_page (Book* self, Page* page); +void G_MODULE_EXPORT save_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT save_as_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +static void simple_scan_draw_page (SimpleScan* self, GtkPrintOperation* operation, GtkPrintContext* print_context, gint page_number); +Page* book_get_page (Book* self, gint page_number); +gboolean page_is_landscape (Page* self); +gint page_get_dpi (Page* self); +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop); +void G_MODULE_EXPORT email_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT print_button_clicked_cb (GtkWidget* widget, SimpleScan* self); +static void _simple_scan_draw_page_gtk_print_operation_draw_page (GtkPrintOperation* _sender, GtkPrintContext* context, gint page_nr, gpointer self); +void G_MODULE_EXPORT help_contents_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +void G_MODULE_EXPORT about_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +static gboolean simple_scan_on_quit (SimpleScan* self); +void G_MODULE_EXPORT quit_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self); +gboolean G_MODULE_EXPORT simple_scan_window_configure_event_cb (GtkWidget* widget, GdkEventConfigure* event, SimpleScan* self); +static void simple_scan_info_bar_response_cb (SimpleScan* self, GtkInfoBar* widget, gint response_id); +gboolean G_MODULE_EXPORT simple_scan_window_window_state_event_cb (GtkWidget* widget, GdkEventWindowState* event, SimpleScan* self); +gboolean G_MODULE_EXPORT window_delete_event_cb (GtkWidget* widget, GdkEvent* event, SimpleScan* self); +static void simple_scan_page_size_changed_cb (SimpleScan* self, Page* page); +static void simple_scan_page_scan_direction_changed_cb (SimpleScan* self, Page* page); +ScanDirection page_get_scan_direction (Page* self); +static void _simple_scan_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self); +static void _simple_scan_page_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self); +static void simple_scan_set_dpi_combo (SimpleScan* self, GtkComboBox* combo, gint default_dpi, gint current_dpi); +static void simple_scan_needs_saving_cb (SimpleScan* self, Book* book); +static void _simple_scan_info_bar_response_cb_gtk_info_bar_response (GtkInfoBar* _sender, gint response_id, gpointer self); +BookView* book_view_new (Book* book); +BookView* book_view_construct (GType object_type, Book* book); +static void _simple_scan_page_selected_cb_book_view_page_selected (BookView* _sender, Page* page, gpointer self); +static void _simple_scan_show_page_cb_book_view_show_page (BookView* _sender, Page* page, gpointer self); +static void _simple_scan_show_page_menu_cb_book_view_show_menu (BookView* _sender, gpointer self); +static void _simple_scan_needs_saving_cb_book_needs_saving_changed (Book* _sender, gpointer self); +Book* simple_scan_get_book (SimpleScan* self); +void simple_scan_set_selected_page (SimpleScan* self, Page* page); +Page* simple_scan_get_selected_page (SimpleScan* self); +void simple_scan_set_scanning (SimpleScan* self, gboolean scanning); +void simple_scan_start (SimpleScan* self); +static void g_cclosure_user_marshal_VOID__STRING_SCAN_OPTIONS (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void simple_scan_finalize (SimpleScan* obj); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); + + +static void _simple_scan_page_removed_cb_book_page_removed (Book* _sender, Page* page, gpointer self) { + simple_scan_page_removed_cb (self, _sender, page); +} + + +static void _simple_scan_page_added_cb_book_page_added (Book* _sender, Page* page, gpointer self) { + simple_scan_page_added_cb (self, _sender, page); +} + + +SimpleScan* simple_scan_construct (GType object_type) { + SimpleScan* self = NULL; + Book* _tmp0_ = NULL; + GSettings* _tmp1_ = NULL; + self = (SimpleScan*) g_type_create_instance (object_type); + _tmp0_ = book_new (); + _book_unref0 (self->priv->book); + self->priv->book = _tmp0_; + g_signal_connect (self->priv->book, "page-removed", (GCallback) _simple_scan_page_removed_cb_book_page_removed, self); + g_signal_connect (self->priv->book, "page-added", (GCallback) _simple_scan_page_added_cb_book_page_added, self); + _tmp1_ = g_settings_new ("org.gnome.SimpleScan"); + _g_object_unref0 (self->priv->settings); + self->priv->settings = _tmp1_; + simple_scan_load (self); + return self; +} + + +SimpleScan* simple_scan_new (void) { + return simple_scan_construct (TYPE_SIMPLE_SCAN); +} + + +static gboolean simple_scan_find_scan_device (SimpleScan* self, const gchar* device, GtkTreeIter* iter) { + GtkTreeIter _iter = {0}; + gboolean result = FALSE; + gboolean have_iter; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (device != NULL, FALSE); + have_iter = FALSE; + _tmp1_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->device_model, &_tmp0_); + _iter = _tmp0_; + if (_tmp1_) { + { + gboolean _tmp2_; + _tmp2_ = TRUE; + while (TRUE) { + gchar* d = NULL; + if (!_tmp2_) { + gboolean _tmp3_ = FALSE; + if (!have_iter) { + gboolean _tmp4_; + _tmp4_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->device_model, &_iter); + _tmp3_ = _tmp4_; + } else { + _tmp3_ = FALSE; + } + if (!_tmp3_) { + break; + } + } + _tmp2_ = FALSE; + gtk_tree_model_get ((GtkTreeModel*) self->priv->device_model, &_iter, 0, &d, -1, -1); + if (g_strcmp0 (d, device) == 0) { + have_iter = TRUE; + } + _g_free0 (d); + } + } + } + result = have_iter; + if (iter) { + *iter = _iter; + } + return result; +} + + +static void simple_scan_show_error_dialog (SimpleScan* self, const gchar* error_title, const gchar* error_text) { + GtkMessageDialog* _tmp0_ = NULL; + GtkMessageDialog* dialog; + g_return_if_fail (self != NULL); + g_return_if_fail (error_title != NULL); + g_return_if_fail (error_text != NULL); + _tmp0_ = (GtkMessageDialog*) gtk_message_dialog_new (self->priv->window, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "%s", error_title); + dialog = g_object_ref_sink (_tmp0_); + gtk_dialog_add_button ((GtkDialog*) dialog, GTK_STOCK_CLOSE, 0); + gtk_message_dialog_format_secondary_text (dialog, "%s", error_text, NULL); + gtk_widget_destroy ((GtkWidget*) dialog); + _g_object_unref0 (dialog); +} + + +void simple_scan_set_default_file_name (SimpleScan* self, const gchar* default_file_name) { + gchar* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (default_file_name != NULL); + _tmp0_ = g_strdup (default_file_name); + _g_free0 (self->priv->default_file_name); + self->priv->default_file_name = _tmp0_; +} + + +void simple_scan_authorize (SimpleScan* self, const gchar* resource, gchar** username, gchar** password) { + gchar* _username = NULL; + gchar* _password = NULL; + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + gchar* description; + const gchar* _tmp2_ = NULL; + gchar* _tmp3_; + const gchar* _tmp4_ = NULL; + gchar* _tmp5_; + g_return_if_fail (self != NULL); + g_return_if_fail (resource != NULL); + _tmp0_ = _ ("Username and password required to access '%s'"); + _tmp1_ = g_strdup_printf (_tmp0_, resource); + description = _tmp1_; + gtk_entry_set_text (self->priv->username_entry, ""); + gtk_entry_set_text (self->priv->password_entry, ""); + gtk_label_set_text (self->priv->authorize_label, description); + gtk_widget_show ((GtkWidget*) self->priv->authorize_dialog); + gtk_dialog_run (self->priv->authorize_dialog); + gtk_widget_hide ((GtkWidget*) self->priv->authorize_dialog); + _tmp2_ = gtk_entry_get_text (self->priv->username_entry); + _tmp3_ = g_strdup (_tmp2_); + _g_free0 (_username); + _username = _tmp3_; + _tmp4_ = gtk_entry_get_text (self->priv->password_entry); + _tmp5_ = g_strdup (_tmp4_); + _g_free0 (_password); + _password = _tmp5_; + _g_free0 (description); + if (username) { + *username = _username; + } else { + _g_free0 (_username); + } + if (password) { + *password = _password; + } else { + _g_free0 (_password); + } +} + + +void G_MODULE_EXPORT device_combo_changed_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + if (self->priv->setting_devices) { + return; + } + self->priv->user_selected_device = TRUE; +} + + +static void simple_scan_update_info_bar (SimpleScan* self) { + GtkMessageType type = 0; + gchar* title = NULL; + gchar* text = NULL; + gchar* image_id = NULL; + gboolean show_close_button; + gboolean show_change_scanner_button; + gchar* _tmp9_ = NULL; + gchar* message; + g_return_if_fail (self != NULL); + show_close_button = FALSE; + show_change_scanner_button = FALSE; + if (self->priv->have_error) { + gchar* _tmp0_; + gchar* _tmp1_; + gchar* _tmp2_; + type = GTK_MESSAGE_ERROR; + _tmp0_ = g_strdup (GTK_STOCK_DIALOG_ERROR); + _g_free0 (image_id); + image_id = _tmp0_; + _tmp1_ = g_strdup (self->priv->error_title); + _g_free0 (title); + title = _tmp1_; + _tmp2_ = g_strdup (self->priv->error_text); + _g_free0 (text); + text = _tmp2_; + show_close_button = TRUE; + show_change_scanner_button = self->priv->error_change_scanner_hint; + } else { + gint _tmp3_; + _tmp3_ = gtk_tree_model_iter_n_children ((GtkTreeModel*) self->priv->device_model, NULL); + if (_tmp3_ == 0) { + gchar* _tmp4_; + const gchar* _tmp5_ = NULL; + gchar* _tmp6_; + const gchar* _tmp7_ = NULL; + gchar* _tmp8_; + type = GTK_MESSAGE_WARNING; + _tmp4_ = g_strdup (GTK_STOCK_DIALOG_WARNING); + _g_free0 (image_id); + image_id = _tmp4_; + _tmp5_ = _ ("No scanners detected"); + _tmp6_ = g_strdup (_tmp5_); + _g_free0 (title); + title = _tmp6_; + _tmp7_ = _ ("Please check your scanner is connected and powered on"); + _tmp8_ = g_strdup (_tmp7_); + _g_free0 (text); + text = _tmp8_; + } else { + gtk_widget_hide ((GtkWidget*) self->priv->info_bar); + _g_free0 (image_id); + _g_free0 (text); + _g_free0 (title); + return; + } + } + gtk_info_bar_set_message_type (self->priv->info_bar, type); + gtk_image_set_from_stock (self->priv->info_bar_image, image_id, GTK_ICON_SIZE_DIALOG); + _tmp9_ = g_strdup_printf ("<big><b>%s</b></big>\n\n%s", title, text); + message = _tmp9_; + gtk_label_set_markup (self->priv->info_bar_label, message); + gtk_widget_set_visible ((GtkWidget*) self->priv->info_bar_close_button, show_close_button); + gtk_widget_set_visible ((GtkWidget*) self->priv->info_bar_change_scanner_button, show_change_scanner_button); + gtk_widget_show ((GtkWidget*) self->priv->info_bar); + _g_free0 (message); + _g_free0 (image_id); + _g_free0 (text); + _g_free0 (title); +} + + +static gpointer _scan_device_ref0 (gpointer self) { + return self ? scan_device_ref (self) : NULL; +} + + +void simple_scan_set_scan_devices (SimpleScan* self, GList* devices) { + gboolean have_selection; + gint index = 0; + GtkTreeIter iter = {0}; + gboolean _tmp11_ = FALSE; + g_return_if_fail (self != NULL); + have_selection = FALSE; + self->priv->setting_devices = TRUE; + if (self->priv->user_selected_device) { + gint _tmp0_; + _tmp0_ = gtk_combo_box_get_active (self->priv->device_combo); + have_selection = _tmp0_ >= 0; + } + index = 0; + { + GList* device_collection = NULL; + GList* device_it = NULL; + device_collection = devices; + for (device_it = device_collection; device_it != NULL; device_it = device_it->next) { + ScanDevice* _tmp1_; + ScanDevice* device = NULL; + _tmp1_ = _scan_device_ref0 ((ScanDevice*) device_it->data); + device = _tmp1_; + { + gint n_delete; + GtkTreeIter _tmp2_ = {0}; + gboolean _tmp3_; + n_delete = -1; + _tmp3_ = gtk_tree_model_iter_nth_child ((GtkTreeModel*) self->priv->device_model, &_tmp2_, NULL, index); + iter = _tmp2_; + if (_tmp3_) { + gint i; + i = 0; + { + gboolean _tmp4_; + _tmp4_ = TRUE; + while (TRUE) { + gchar* name = NULL; + gboolean matched = FALSE; + if (!_tmp4_) { + gboolean _tmp5_; + _tmp5_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->device_model, &iter); + if (!_tmp5_) { + break; + } + } + _tmp4_ = FALSE; + gtk_tree_model_get ((GtkTreeModel*) self->priv->device_model, &iter, 0, &name, -1, -1); + matched = g_strcmp0 (name, device->name) == 0; + if (matched) { + n_delete = i; + _g_free0 (name); + break; + } + i++; + _g_free0 (name); + } + } + } + if (n_delete >= 0) { + gint i = 0; + gtk_list_store_set (self->priv->device_model, &iter, 1, device->label, -1, -1); + { + gboolean _tmp6_; + i = 0; + _tmp6_ = TRUE; + while (TRUE) { + GtkTreeIter _tmp7_ = {0}; + if (!_tmp6_) { + i++; + } + _tmp6_ = FALSE; + if (!(i < n_delete)) { + break; + } + gtk_tree_model_iter_nth_child ((GtkTreeModel*) self->priv->device_model, &_tmp7_, NULL, index); + iter = _tmp7_; + gtk_list_store_remove (self->priv->device_model, &iter); + } + } + } else { + GtkTreeIter _tmp8_ = {0}; + gtk_list_store_insert (self->priv->device_model, &_tmp8_, index); + iter = _tmp8_; + gtk_list_store_set (self->priv->device_model, &iter, 0, device->name, 1, device->label, -1, -1); + } + index++; + _scan_device_unref0 (device); + } + } + } + while (TRUE) { + GtkTreeIter _tmp9_ = {0}; + gboolean _tmp10_; + _tmp10_ = gtk_tree_model_iter_nth_child ((GtkTreeModel*) self->priv->device_model, &_tmp9_, NULL, index); + iter = _tmp9_; + if (!_tmp10_) { + break; + } + gtk_list_store_remove (self->priv->device_model, &iter); + } + if (!have_selection) { + _tmp11_ = devices != NULL; + } else { + _tmp11_ = FALSE; + } + if (_tmp11_) { + gtk_combo_box_set_active (self->priv->device_combo, 0); + } + self->priv->setting_devices = FALSE; + simple_scan_update_info_bar (self); +} + + +static gchar* simple_scan_get_selected_device (SimpleScan* self) { + gchar* result = NULL; + GtkTreeIter iter = {0}; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_val_if_fail (self != NULL, NULL); + _tmp1_ = gtk_combo_box_get_active_iter (self->priv->device_combo, &_tmp0_); + iter = _tmp0_; + if (_tmp1_) { + gchar* device = NULL; + gtk_tree_model_get ((GtkTreeModel*) self->priv->device_model, &iter, 0, &device, -1, -1); + result = device; + return result; + } + result = NULL; + return result; +} + + +void simple_scan_set_selected_device (SimpleScan* self, const gchar* device) { + GtkTreeIter iter = {0}; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (device != NULL); + _tmp1_ = simple_scan_find_scan_device (self, device, &_tmp0_); + iter = _tmp0_; + if (!_tmp1_) { + return; + } + gtk_combo_box_set_active_iter (self->priv->device_combo, &iter); + self->priv->user_selected_device = TRUE; +} + + +static void simple_scan_add_default_page (SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + _tmp0_ = book_append_page (self->priv->book, self->priv->default_page_width, self->priv->default_page_height, self->priv->default_page_dpi, self->priv->default_page_scan_direction); + page = _tmp0_; + book_view_select_page (self->priv->book_view, page); + _page_unref0 (page); +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +static gint string_last_index_of_char (const gchar* self, gunichar c, gint start_index) { + gint result = 0; + gchar* _tmp0_ = NULL; + gchar* _result_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = g_utf8_strrchr (((gchar*) self) + start_index, (gssize) (-1), c); + _result_ = _tmp0_; + if (_result_ != NULL) { + result = (gint) (_result_ - ((gchar*) self)); + return result; + } else { + result = -1; + return result; + } +} + + +static gchar* string_slice (const gchar* self, glong start, glong end) { + gchar* result = NULL; + gint _tmp0_; + glong string_length; + gboolean _tmp1_ = FALSE; + gboolean _tmp2_ = FALSE; + gchar* _tmp3_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = strlen (self); + string_length = (glong) _tmp0_; + if (start < ((glong) 0)) { + start = string_length + start; + } + if (end < ((glong) 0)) { + end = string_length + end; + } + if (start >= ((glong) 0)) { + _tmp1_ = start <= string_length; + } else { + _tmp1_ = FALSE; + } + g_return_val_if_fail (_tmp1_, NULL); + if (end >= ((glong) 0)) { + _tmp2_ = end <= string_length; + } else { + _tmp2_ = FALSE; + } + g_return_val_if_fail (_tmp2_, NULL); + g_return_val_if_fail (start <= end, NULL); + _tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start)); + result = _tmp3_; + return result; +} + + +static void simple_scan_on_file_type_changed (SimpleScan* self, GtkTreeSelection* selection) { + GtkTreeModel* model = NULL; + GtkTreeIter iter = {0}; + GtkTreeModel* _tmp0_ = NULL; + GtkTreeIter _tmp1_ = {0}; + gboolean _tmp2_; + GtkTreeModel* _tmp3_; + gchar* extension = NULL; + gchar* _tmp4_ = NULL; + gchar* path; + gchar* _tmp5_ = NULL; + gchar* filename; + gint _tmp6_; + gint extension_index; + gchar* _tmp8_; + g_return_if_fail (self != NULL); + g_return_if_fail (selection != NULL); + _tmp2_ = gtk_tree_selection_get_selected (selection, &_tmp0_, &_tmp1_); + _g_object_unref0 (model); + _tmp3_ = _g_object_ref0 (_tmp0_); + model = _tmp3_; + iter = _tmp1_; + if (!_tmp2_) { + _g_object_unref0 (model); + return; + } + gtk_tree_model_get (model, &iter, 1, &extension, -1, -1); + _tmp4_ = gtk_file_chooser_get_filename ((GtkFileChooser*) self->priv->save_dialog); + path = _tmp4_; + _tmp5_ = g_path_get_basename (path); + filename = _tmp5_; + _tmp6_ = string_last_index_of_char (filename, (gunichar) '.', 0); + extension_index = _tmp6_; + if (extension_index >= 0) { + gchar* _tmp7_ = NULL; + _tmp7_ = string_slice (filename, (glong) 0, (glong) extension_index); + _g_free0 (filename); + filename = _tmp7_; + } + _tmp8_ = g_strconcat (filename, extension, NULL); + _g_free0 (filename); + filename = _tmp8_; + gtk_file_chooser_set_current_name ((GtkFileChooser*) self->priv->save_dialog, filename); + _g_free0 (filename); + _g_free0 (path); + _g_free0 (extension); + _g_object_unref0 (model); +} + + +static void _simple_scan_on_file_type_changed_gtk_tree_selection_changed (GtkTreeSelection* _sender, gpointer self) { + simple_scan_on_file_type_changed (self, _sender); +} + + +static gchar* simple_scan_choose_file_location (SimpleScan* self) { + gchar* result = NULL; + gchar* directory; + gchar* _tmp0_ = NULL; + gboolean _tmp1_ = FALSE; + const gchar* _tmp4_ = NULL; + GtkFileChooserDialog* _tmp5_ = NULL; + GtkFileFilter* _tmp6_ = NULL; + GtkFileFilter* filter; + const gchar* _tmp7_ = NULL; + GtkFileFilter* _tmp8_ = NULL; + const gchar* _tmp9_ = NULL; + const gchar* _tmp10_ = NULL; + GtkExpander* _tmp11_ = NULL; + GtkExpander* expander; + gchar* _tmp12_; + gchar* extension; + gint _tmp13_; + gint index; + GtkListStore* _tmp15_ = NULL; + GtkListStore* file_type_store; + GtkTreeIter iter = {0}; + GtkTreeIter _tmp16_ = {0}; + const gchar* _tmp17_ = NULL; + GtkTreeIter _tmp18_ = {0}; + const gchar* _tmp19_ = NULL; + GtkTreeIter _tmp20_ = {0}; + const gchar* _tmp21_ = NULL; + GtkTreeView* _tmp22_ = NULL; + GtkTreeView* file_type_view; + GtkCellRendererText* _tmp23_ = NULL; + GtkCellRendererText* _tmp24_; + GtkTreeViewColumn* _tmp25_ = NULL; + GtkTreeViewColumn* _tmp26_; + GtkTreeViewColumn* column; + GtkTreeIter _tmp27_ = {0}; + gboolean _tmp28_; + GtkTreeSelection* _tmp32_ = NULL; + gint _tmp33_; + gint response; + gchar* uri; + gchar* _tmp35_ = NULL; + gchar* _tmp36_; + g_return_val_if_fail (self != NULL, NULL); + directory = NULL; + _tmp0_ = g_settings_get_string (self->priv->settings, "save-directory"); + _g_free0 (directory); + directory = _tmp0_; + if (directory == NULL) { + _tmp1_ = TRUE; + } else { + _tmp1_ = g_strcmp0 (directory, "") == 0; + } + if (_tmp1_) { + const gchar* _tmp2_ = NULL; + gchar* _tmp3_; + _tmp2_ = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + _tmp3_ = g_strdup (_tmp2_); + _g_free0 (directory); + directory = _tmp3_; + } + _tmp4_ = _ ("Save As..."); + _tmp5_ = (GtkFileChooserDialog*) gtk_file_chooser_dialog_new (_tmp4_, self->priv->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL, NULL); + _g_object_unref0 (self->priv->save_dialog); + self->priv->save_dialog = g_object_ref_sink (_tmp5_); + gtk_file_chooser_set_do_overwrite_confirmation ((GtkFileChooser*) self->priv->save_dialog, TRUE); + gtk_file_chooser_set_local_only ((GtkFileChooser*) self->priv->save_dialog, FALSE); + gtk_file_chooser_set_current_folder ((GtkFileChooser*) self->priv->save_dialog, directory); + gtk_file_chooser_set_current_name ((GtkFileChooser*) self->priv->save_dialog, self->priv->default_file_name); + _tmp6_ = gtk_file_filter_new (); + filter = g_object_ref_sink (_tmp6_); + _tmp7_ = _ ("Image Files"); + gtk_buildable_set_name ((GtkBuildable*) filter, _tmp7_); + gtk_file_filter_add_pixbuf_formats (filter); + gtk_file_filter_add_mime_type (filter, "application/pdf"); + gtk_file_chooser_add_filter ((GtkFileChooser*) self->priv->save_dialog, filter); + _tmp8_ = gtk_file_filter_new (); + _g_object_unref0 (filter); + filter = g_object_ref_sink (_tmp8_); + _tmp9_ = _ ("All Files"); + gtk_buildable_set_name ((GtkBuildable*) filter, _tmp9_); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter ((GtkFileChooser*) self->priv->save_dialog, filter); + _tmp10_ = _ ("Select File _Type"); + _tmp11_ = (GtkExpander*) gtk_expander_new_with_mnemonic (_tmp10_); + expander = g_object_ref_sink (_tmp11_); + gtk_expander_set_spacing (expander, 5); + gtk_file_chooser_set_extra_widget ((GtkFileChooser*) self->priv->save_dialog, (GtkWidget*) expander); + _tmp12_ = g_strdup (""); + extension = _tmp12_; + _tmp13_ = string_last_index_of_char (self->priv->default_file_name, (gunichar) '.', 0); + index = _tmp13_; + if (index >= 0) { + gchar* _tmp14_ = NULL; + _tmp14_ = string_slice (self->priv->default_file_name, (glong) 0, (glong) index); + _g_free0 (extension); + extension = _tmp14_; + } + _tmp15_ = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + file_type_store = _tmp15_; + gtk_list_store_append (file_type_store, &_tmp16_); + iter = _tmp16_; + _tmp17_ = _ ("PDF (multi-page document)"); + gtk_list_store_set (file_type_store, &iter, 0, _tmp17_, 1, ".pdf", -1, -1); + gtk_list_store_append (file_type_store, &_tmp18_); + iter = _tmp18_; + _tmp19_ = _ ("JPEG (compressed)"); + gtk_list_store_set (file_type_store, &iter, 0, _tmp19_, 1, ".jpg", -1, -1); + gtk_list_store_append (file_type_store, &_tmp20_); + iter = _tmp20_; + _tmp21_ = _ ("PNG (lossless)"); + gtk_list_store_set (file_type_store, &iter, 0, _tmp21_, 1, ".png", -1, -1); + _tmp22_ = (GtkTreeView*) gtk_tree_view_new_with_model ((GtkTreeModel*) file_type_store); + file_type_view = g_object_ref_sink (_tmp22_); + gtk_tree_view_set_headers_visible (file_type_view, FALSE); + gtk_tree_view_set_rules_hint (file_type_view, TRUE); + _tmp23_ = (GtkCellRendererText*) gtk_cell_renderer_text_new (); + _tmp24_ = g_object_ref_sink (_tmp23_); + _tmp25_ = gtk_tree_view_column_new_with_attributes ("", (GtkCellRenderer*) _tmp24_, "text", 0, NULL, NULL); + _tmp26_ = g_object_ref_sink (_tmp25_); + _g_object_unref0 (_tmp24_); + column = _tmp26_; + gtk_tree_view_append_column (file_type_view, column); + gtk_container_add ((GtkContainer*) expander, (GtkWidget*) file_type_view); + _tmp28_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) file_type_store, &_tmp27_); + iter = _tmp27_; + if (_tmp28_) { + { + gboolean _tmp29_; + _tmp29_ = TRUE; + while (TRUE) { + gchar* e = NULL; + if (!_tmp29_) { + gboolean _tmp30_; + _tmp30_ = gtk_tree_model_iter_next ((GtkTreeModel*) file_type_store, &iter); + if (!_tmp30_) { + break; + } + } + _tmp29_ = FALSE; + gtk_tree_model_get ((GtkTreeModel*) file_type_store, &iter, 1, &e, -1, -1); + if (g_strcmp0 (extension, e) == 0) { + GtkTreeSelection* _tmp31_ = NULL; + _tmp31_ = gtk_tree_view_get_selection (file_type_view); + gtk_tree_selection_select_iter (_tmp31_, &iter); + } + _g_free0 (e); + } + } + } + _tmp32_ = gtk_tree_view_get_selection (file_type_view); + g_signal_connect (_tmp32_, "changed", (GCallback) _simple_scan_on_file_type_changed_gtk_tree_selection_changed, self); + gtk_widget_show_all ((GtkWidget*) expander); + _tmp33_ = gtk_dialog_run ((GtkDialog*) self->priv->save_dialog); + response = _tmp33_; + uri = NULL; + if (response == ((gint) GTK_RESPONSE_ACCEPT)) { + gchar* _tmp34_ = NULL; + _tmp34_ = gtk_file_chooser_get_uri ((GtkFileChooser*) self->priv->save_dialog); + _g_free0 (uri); + uri = _tmp34_; + } + _tmp35_ = gtk_file_chooser_get_current_folder ((GtkFileChooser*) self->priv->save_dialog); + _tmp36_ = _tmp35_; + g_settings_set_string (self->priv->settings, "save-directory", _tmp36_); + _g_free0 (_tmp36_); + gtk_widget_destroy ((GtkWidget*) self->priv->save_dialog); + _g_object_unref0 (self->priv->save_dialog); + self->priv->save_dialog = NULL; + result = uri; + _g_object_unref0 (column); + _g_object_unref0 (file_type_view); + _g_object_unref0 (file_type_store); + _g_free0 (extension); + _g_object_unref0 (expander); + _g_object_unref0 (filter); + _g_free0 (directory); + return result; +} + + +static gboolean simple_scan_save_document (SimpleScan* self, gboolean force_choose_location) { + gboolean result = FALSE; + gchar* uri = NULL; + gboolean _tmp0_ = FALSE; + GFile* _tmp3_ = NULL; + GFile* file; + gchar* _tmp4_ = NULL; + gchar* uri_lower; + gchar* _tmp5_; + gchar* format; + gboolean _tmp6_; + gchar* _tmp17_; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, FALSE); + if (self->priv->book_uri != NULL) { + _tmp0_ = !force_choose_location; + } else { + _tmp0_ = FALSE; + } + if (_tmp0_) { + gchar* _tmp1_; + _tmp1_ = g_strdup (self->priv->book_uri); + _g_free0 (uri); + uri = _tmp1_; + } else { + gchar* _tmp2_ = NULL; + _tmp2_ = simple_scan_choose_file_location (self); + _g_free0 (uri); + uri = _tmp2_; + } + if (uri == NULL) { + result = FALSE; + _g_free0 (uri); + return result; + } + _tmp3_ = g_file_new_for_uri (uri); + file = _tmp3_; + g_debug ("ui.vala:445: Saving to '%s'", uri); + _tmp4_ = g_utf8_strdown (uri, (gssize) (-1)); + uri_lower = _tmp4_; + _tmp5_ = g_strdup ("jpeg"); + format = _tmp5_; + _tmp6_ = g_str_has_suffix (uri_lower, ".pdf"); + if (_tmp6_) { + gchar* _tmp7_; + _tmp7_ = g_strdup ("pdf"); + _g_free0 (format); + format = _tmp7_; + } else { + gboolean _tmp8_; + _tmp8_ = g_str_has_suffix (uri_lower, ".ps"); + if (_tmp8_) { + gchar* _tmp9_; + _tmp9_ = g_strdup ("ps"); + _g_free0 (format); + format = _tmp9_; + } else { + gboolean _tmp10_; + _tmp10_ = g_str_has_suffix (uri_lower, ".png"); + if (_tmp10_) { + gchar* _tmp11_; + _tmp11_ = g_strdup ("png"); + _g_free0 (format); + format = _tmp11_; + } else { + gboolean _tmp12_ = FALSE; + gboolean _tmp13_; + _tmp13_ = g_str_has_suffix (uri_lower, ".tif"); + if (_tmp13_) { + _tmp12_ = TRUE; + } else { + gboolean _tmp14_; + _tmp14_ = g_str_has_suffix (uri_lower, ".tiff"); + _tmp12_ = _tmp14_; + } + if (_tmp12_) { + gchar* _tmp15_; + _tmp15_ = g_strdup ("tiff"); + _g_free0 (format); + format = _tmp15_; + } + } + } + } + { + book_save (self->priv->book, format, file, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch10_g_error; + } + } + goto __finally10; + __catch10_g_error: + { + GError* e = NULL; + const gchar* _tmp16_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("ui.vala:464: Error saving file: %s", e->message); + _tmp16_ = _ ("Failed to save file"); + simple_scan_show_error (self, _tmp16_, e->message, FALSE); + result = FALSE; + _g_error_free0 (e); + _g_free0 (format); + _g_free0 (uri_lower); + _g_object_unref0 (file); + _g_free0 (uri); + return result; + } + __finally10: + if (_inner_error_ != NULL) { + _g_free0 (format); + _g_free0 (uri_lower); + _g_object_unref0 (file); + _g_free0 (uri); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + _tmp17_ = g_strdup (uri); + _g_free0 (self->priv->book_uri); + self->priv->book_uri = _tmp17_; + book_set_needs_saving (self->priv->book, FALSE); + result = TRUE; + _g_free0 (format); + _g_free0 (uri_lower); + _g_object_unref0 (file); + _g_free0 (uri); + return result; +} + + +static gboolean simple_scan_prompt_to_save (SimpleScan* self, const gchar* title, const gchar* discard_label) { + gboolean result = FALSE; + gboolean _tmp0_; + GtkMessageDialog* _tmp1_ = NULL; + GtkMessageDialog* dialog; + const gchar* _tmp2_ = NULL; + gint _tmp3_; + gint response; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (title != NULL, FALSE); + g_return_val_if_fail (discard_label != NULL, FALSE); + _tmp0_ = book_get_needs_saving (self->priv->book); + if (!_tmp0_) { + result = TRUE; + return result; + } + _tmp1_ = (GtkMessageDialog*) gtk_message_dialog_new (self->priv->window, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "%s", title); + dialog = g_object_ref_sink (_tmp1_); + _tmp2_ = _ ("If you don't save, changes will be permanently lost."); + gtk_message_dialog_format_secondary_text (dialog, "%s", _tmp2_, NULL); + gtk_dialog_add_button ((GtkDialog*) dialog, discard_label, (gint) GTK_RESPONSE_NO); + gtk_dialog_add_button ((GtkDialog*) dialog, GTK_STOCK_CANCEL, (gint) GTK_RESPONSE_CANCEL); + gtk_dialog_add_button ((GtkDialog*) dialog, GTK_STOCK_SAVE, (gint) GTK_RESPONSE_YES); + _tmp3_ = gtk_dialog_run ((GtkDialog*) dialog); + response = _tmp3_; + gtk_widget_destroy ((GtkWidget*) dialog); + switch (response) { + case GTK_RESPONSE_YES: + { + gboolean _tmp4_; + _tmp4_ = simple_scan_save_document (self, FALSE); + if (_tmp4_) { + result = TRUE; + _g_object_unref0 (dialog); + return result; + } else { + result = FALSE; + _g_object_unref0 (dialog); + return result; + } + } + case GTK_RESPONSE_CANCEL: + { + result = FALSE; + _g_object_unref0 (dialog); + return result; + } + default: + case GTK_RESPONSE_NO: + { + result = TRUE; + _g_object_unref0 (dialog); + return result; + } + } + _g_object_unref0 (dialog); +} + + +static void simple_scan_clear_document (SimpleScan* self) { + g_return_if_fail (self != NULL); + book_clear (self->priv->book); + simple_scan_add_default_page (self); + _g_free0 (self->priv->book_uri); + self->priv->book_uri = NULL; + book_set_needs_saving (self->priv->book, FALSE); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_as_menuitem, FALSE); +} + + +void G_MODULE_EXPORT new_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + const gchar* _tmp0_ = NULL; + const gchar* _tmp1_ = NULL; + gboolean _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = _ ("Save current document?"); + _tmp1_ = _ ("Discard Changes"); + _tmp2_ = simple_scan_prompt_to_save (self, _tmp0_, _tmp1_); + if (!_tmp2_) { + return; + } + simple_scan_clear_document (self); +} + + +static void simple_scan_set_document_hint (SimpleScan* self, const gchar* document_hint) { + gchar* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (document_hint != NULL); + _tmp0_ = g_strdup (document_hint); + _g_free0 (self->priv->document_hint); + self->priv->document_hint = _tmp0_; + if (g_strcmp0 (document_hint, "text") == 0) { + gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->text_toolbar_menuitem, TRUE); + gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->text_menu_menuitem, TRUE); + } else { + if (g_strcmp0 (document_hint, "photo") == 0) { + gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->photo_toolbar_menuitem, TRUE); + gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->photo_menu_menuitem, TRUE); + } + } +} + + +void G_MODULE_EXPORT text_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_document_hint (self, "text"); + } +} + + +void G_MODULE_EXPORT photo_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_document_hint (self, "photo"); + } +} + + +static void simple_scan_set_page_side (SimpleScan* self, ScanType page_side) { + GtkTreeIter iter = {0}; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_if_fail (self != NULL); + _tmp1_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->page_side_model, &_tmp0_); + iter = _tmp0_; + if (_tmp1_) { + { + gboolean _tmp2_; + _tmp2_ = TRUE; + while (TRUE) { + gint s = 0; + if (!_tmp2_) { + gboolean _tmp3_; + _tmp3_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->page_side_model, &iter); + if (!_tmp3_) { + break; + } + } + _tmp2_ = FALSE; + gtk_tree_model_get ((GtkTreeModel*) self->priv->page_side_model, &iter, 0, &s, -1, -1); + if (s == ((gint) page_side)) { + gtk_combo_box_set_active_iter (self->priv->page_side_combo, &iter); + return; + } + } + } + } +} + + +static void simple_scan_set_paper_size (SimpleScan* self, gint width, gint height) { + GtkTreeIter iter = {0}; + gboolean have_iter = FALSE; + g_return_if_fail (self != NULL); + { + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + gboolean _tmp2_; + _tmp1_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->paper_size_model, &_tmp0_); + iter = _tmp0_; + have_iter = _tmp1_; + _tmp2_ = TRUE; + while (TRUE) { + gint w = 0; + gint h = 0; + gboolean _tmp4_ = FALSE; + if (!_tmp2_) { + gboolean _tmp3_; + _tmp3_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->paper_size_model, &iter); + have_iter = _tmp3_; + } + _tmp2_ = FALSE; + if (!have_iter) { + break; + } + gtk_tree_model_get ((GtkTreeModel*) self->priv->paper_size_model, &iter, 0, &w, 1, &h, -1, -1); + if (w == width) { + _tmp4_ = h == height; + } else { + _tmp4_ = FALSE; + } + if (_tmp4_) { + break; + } + } + } + if (!have_iter) { + GtkTreeIter _tmp5_ = {0}; + gboolean _tmp6_; + _tmp6_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->paper_size_model, &_tmp5_); + iter = _tmp5_; + have_iter = _tmp6_; + } + if (have_iter) { + gtk_combo_box_set_active_iter (self->priv->paper_size_combo, &iter); + } +} + + +static gint simple_scan_get_text_dpi (SimpleScan* self) { + gint result = 0; + GtkTreeIter iter = {0}; + gint dpi; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_val_if_fail (self != NULL, 0); + dpi = SIMPLE_SCAN_DEFAULT_TEXT_DPI; + _tmp1_ = gtk_combo_box_get_active_iter (self->priv->text_dpi_combo, &_tmp0_); + iter = _tmp0_; + if (_tmp1_) { + gtk_tree_model_get ((GtkTreeModel*) self->priv->text_dpi_model, &iter, 0, &dpi, -1, -1); + } + result = dpi; + return result; +} + + +static gint simple_scan_get_photo_dpi (SimpleScan* self) { + gint result = 0; + GtkTreeIter iter = {0}; + gint dpi; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_val_if_fail (self != NULL, 0); + dpi = SIMPLE_SCAN_DEFAULT_PHOTO_DPI; + _tmp1_ = gtk_combo_box_get_active_iter (self->priv->photo_dpi_combo, &_tmp0_); + iter = _tmp0_; + if (_tmp1_) { + gtk_tree_model_get ((GtkTreeModel*) self->priv->photo_dpi_model, &iter, 0, &dpi, -1, -1); + } + result = dpi; + return result; +} + + +static ScanType simple_scan_get_page_side (SimpleScan* self) { + ScanType result = 0; + GtkTreeIter iter = {0}; + gint page_side; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_val_if_fail (self != NULL, 0); + page_side = (gint) SCAN_TYPE_ADF_BOTH; + _tmp1_ = gtk_combo_box_get_active_iter (self->priv->page_side_combo, &_tmp0_); + iter = _tmp0_; + if (_tmp1_) { + gtk_tree_model_get ((GtkTreeModel*) self->priv->page_side_model, &iter, 0, &page_side, -1, -1); + } + result = (ScanType) page_side; + return result; +} + + +static gboolean simple_scan_get_paper_size (SimpleScan* self, gint* width, gint* height) { + gint _width = 0; + gint _height = 0; + gboolean result = FALSE; + GtkTreeIter iter = {0}; + GtkTreeIter _tmp0_ = {0}; + gboolean _tmp1_; + g_return_val_if_fail (self != NULL, FALSE); + _tmp1_ = gtk_combo_box_get_active_iter (self->priv->paper_size_combo, &_tmp0_); + iter = _tmp0_; + if (_tmp1_) { + gtk_tree_model_get ((GtkTreeModel*) self->priv->paper_size_model, &iter, 0, &_width, 1, &_height, -1, -1); + result = TRUE; + if (width) { + *width = _width; + } + if (height) { + *height = _height; + } + return result; + } + result = FALSE; + if (width) { + *width = _width; + } + if (height) { + *height = _height; + } + return result; +} + + +static ScanOptions* simple_scan_get_scan_options (SimpleScan* self) { + ScanOptions* result = NULL; + ScanOptions* _tmp0_ = NULL; + ScanOptions* options; + gint _tmp3_; + gint _tmp4_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = scan_options_new (); + options = _tmp0_; + if (g_strcmp0 (self->priv->document_hint, "text") == 0) { + gint _tmp1_; + options->scan_mode = SCAN_MODE_GRAY; + _tmp1_ = simple_scan_get_text_dpi (self); + options->dpi = _tmp1_; + options->depth = 2; + } else { + gint _tmp2_; + options->scan_mode = SCAN_MODE_COLOR; + _tmp2_ = simple_scan_get_photo_dpi (self); + options->dpi = _tmp2_; + options->depth = 8; + } + simple_scan_get_paper_size (self, &_tmp3_, &_tmp4_); + options->paper_width = _tmp3_; + options->paper_height = _tmp4_; + result = options; + return result; +} + + +void G_MODULE_EXPORT scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + ScanOptions* _tmp0_ = NULL; + ScanOptions* options; + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = simple_scan_get_scan_options (self); + options = _tmp0_; + options->type = SCAN_TYPE_SINGLE; + _tmp1_ = simple_scan_get_selected_device (self); + _tmp2_ = _tmp1_; + g_signal_emit_by_name (self, "start-scan", _tmp2_, options); + _g_free0 (_tmp2_); + _scan_options_unref0 (options); +} + + +void G_MODULE_EXPORT stop_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + g_signal_emit_by_name (self, "stop-scan"); +} + + +void G_MODULE_EXPORT continuous_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + if (self->priv->scanning) { + g_signal_emit_by_name (self, "stop-scan"); + } else { + ScanOptions* _tmp0_ = NULL; + ScanOptions* options; + ScanType _tmp1_; + gchar* _tmp2_ = NULL; + gchar* _tmp3_; + _tmp0_ = simple_scan_get_scan_options (self); + options = _tmp0_; + _tmp1_ = simple_scan_get_page_side (self); + options->type = _tmp1_; + _tmp2_ = simple_scan_get_selected_device (self); + _tmp3_ = _tmp2_; + g_signal_emit_by_name (self, "start-scan", _tmp3_, options); + _g_free0 (_tmp3_); + _scan_options_unref0 (options); + } +} + + +void G_MODULE_EXPORT preferences_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + gtk_window_present ((GtkWindow*) self->priv->preferences_dialog); +} + + +gboolean G_MODULE_EXPORT preferences_dialog_delete_event_cb (GtkWidget* widget, SimpleScan* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + result = TRUE; + return result; +} + + +void G_MODULE_EXPORT preferences_dialog_response_cb (GtkWidget* widget, gint response_id, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + gtk_widget_hide ((GtkWidget*) self->priv->preferences_dialog); +} + + +static void simple_scan_update_page_menu (SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + if (page == NULL) { + gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_left_menuitem, FALSE); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_right_menuitem, FALSE); + } else { + guint _tmp1_; + guint index; + guint _tmp2_; + _tmp1_ = book_get_page_index (self->priv->book, page); + index = _tmp1_; + gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_left_menuitem, index > ((guint) 0)); + _tmp2_ = book_get_n_pages (self->priv->book); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_right_menuitem, index < (_tmp2_ - 1)); + } + _page_unref0 (page); +} + + +static void simple_scan_page_selected_cb (SimpleScan* self, BookView* view, Page* page) { + gchar* name; + gboolean _tmp0_; + GObject* _tmp10_ = NULL; + GtkRadioMenuItem* _tmp11_; + GtkRadioMenuItem* menuitem; + GObject* _tmp12_ = NULL; + GtkToggleToolButton* _tmp13_; + GtkToggleToolButton* toolbutton; + gboolean _tmp14_; + g_return_if_fail (self != NULL); + g_return_if_fail (view != NULL); + if (page == NULL) { + return; + } + self->priv->updating_page_menu = TRUE; + simple_scan_update_page_menu (self); + name = NULL; + _tmp0_ = page_has_crop (page); + if (_tmp0_) { + gchar* _tmp1_ = NULL; + gchar* crop_name; + _tmp1_ = page_get_named_crop (page); + crop_name = _tmp1_; + if (crop_name != NULL) { + if (g_strcmp0 (crop_name, "A4") == 0) { + gchar* _tmp2_; + _tmp2_ = g_strdup ("a4_menuitem"); + _g_free0 (name); + name = _tmp2_; + } else { + if (g_strcmp0 (crop_name, "A5") == 0) { + gchar* _tmp3_; + _tmp3_ = g_strdup ("a5_menuitem"); + _g_free0 (name); + name = _tmp3_; + } else { + if (g_strcmp0 (crop_name, "A6") == 0) { + gchar* _tmp4_; + _tmp4_ = g_strdup ("a6_menuitem"); + _g_free0 (name); + name = _tmp4_; + } else { + if (g_strcmp0 (crop_name, "letter") == 0) { + gchar* _tmp5_; + _tmp5_ = g_strdup ("letter_menuitem"); + _g_free0 (name); + name = _tmp5_; + } else { + if (g_strcmp0 (crop_name, "legal") == 0) { + gchar* _tmp6_; + _tmp6_ = g_strdup ("legal_menuitem"); + _g_free0 (name); + name = _tmp6_; + } else { + if (g_strcmp0 (crop_name, "4x6") == 0) { + gchar* _tmp7_; + _tmp7_ = g_strdup ("4x6_menuitem"); + _g_free0 (name); + name = _tmp7_; + } + } + } + } + } + } + } else { + gchar* _tmp8_; + _tmp8_ = g_strdup ("custom_crop_menuitem"); + _g_free0 (name); + name = _tmp8_; + } + _g_free0 (crop_name); + } else { + gchar* _tmp9_; + _tmp9_ = g_strdup ("no_crop_menuitem"); + _g_free0 (name); + name = _tmp9_; + } + _tmp10_ = gtk_builder_get_object (self->priv->builder, name); + _tmp11_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp10_)); + menuitem = _tmp11_; + gtk_check_menu_item_set_active ((GtkCheckMenuItem*) menuitem, TRUE); + _tmp12_ = gtk_builder_get_object (self->priv->builder, "crop_toolbutton"); + _tmp13_ = _g_object_ref0 (GTK_TOGGLE_TOOL_BUTTON (_tmp12_)); + toolbutton = _tmp13_; + _tmp14_ = page_has_crop (page); + gtk_toggle_tool_button_set_active (toolbutton, _tmp14_); + self->priv->updating_page_menu = FALSE; + _g_object_unref0 (toolbutton); + _g_object_unref0 (menuitem); + _g_free0 (name); +} + + +static gchar* simple_scan_get_temporary_filename (SimpleScan* self, const gchar* prefix, const gchar* extension) { + gchar* result = NULL; + gchar* _tmp0_ = NULL; + gchar* filename; + gchar* path = NULL; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (prefix != NULL, NULL); + g_return_val_if_fail (extension != NULL, NULL); + _tmp0_ = g_strdup_printf ("%sXXXXXX.%s", prefix, extension); + filename = _tmp0_; + { + gchar* _tmp1_ = NULL; + gint _tmp2_; + gint fd; + _tmp2_ = g_file_open_tmp (filename, &_tmp1_, &_inner_error_); + _g_free0 (path); + path = _tmp1_; + fd = _tmp2_; + if (_inner_error_ != NULL) { + goto __catch11_g_error; + } + close (fd); + } + goto __finally11; + __catch11_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("ui.vala:788: Error saving email attachment: %s", e->message); + result = NULL; + _g_error_free0 (e); + _g_free0 (path); + _g_free0 (filename); + return result; + } + __finally11: + if (_inner_error_ != NULL) { + _g_free0 (path); + _g_free0 (filename); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + result = path; + _g_free0 (filename); + return result; +} + + +static void simple_scan_show_page_cb (SimpleScan* self, BookView* view, Page* page) { + gchar* _tmp0_ = NULL; + gchar* path; + GFile* _tmp1_ = NULL; + GFile* file; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (view != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = simple_scan_get_temporary_filename (self, "scanned-page", "tiff"); + path = _tmp0_; + if (path == NULL) { + _g_free0 (path); + return; + } + _tmp1_ = g_file_new_for_path (path); + file = _tmp1_; + { + page_save (page, "tiff", file, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch12_g_error; + } + } + goto __finally12; + __catch12_g_error: + { + GError* e = NULL; + const gchar* _tmp2_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + _tmp2_ = _ ("Unable to save image for preview"); + simple_scan_show_error_dialog (self, _tmp2_, e->message); + _g_error_free0 (e); + _g_object_unref0 (file); + _g_free0 (path); + return; + } + __finally12: + if (_inner_error_ != NULL) { + _g_object_unref0 (file); + _g_free0 (path); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + { + GdkScreen* _tmp3_ = NULL; + gchar* _tmp4_ = NULL; + gchar* _tmp5_; + guint32 _tmp6_; + _tmp3_ = gtk_window_get_screen (self->priv->window); + _tmp4_ = g_file_get_uri (file); + _tmp5_ = _tmp4_; + _tmp6_ = gtk_get_current_event_time (); + gtk_show_uri (_tmp3_, _tmp5_, _tmp6_, &_inner_error_); + _g_free0 (_tmp5_); + if (_inner_error_ != NULL) { + goto __catch13_g_error; + } + } + goto __finally13; + __catch13_g_error: + { + GError* e = NULL; + const gchar* _tmp7_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + _tmp7_ = _ ("Unable to open image preview application"); + simple_scan_show_error_dialog (self, _tmp7_, e->message); + _g_error_free0 (e); + } + __finally13: + if (_inner_error_ != NULL) { + _g_object_unref0 (file); + _g_free0 (path); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + _g_object_unref0 (file); + _g_free0 (path); +} + + +static void simple_scan_show_page_menu_cb (SimpleScan* self, BookView* view) { + GObject* _tmp0_ = NULL; + GtkMenu* _tmp1_; + GtkMenu* menu; + guint32 _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (view != NULL); + _tmp0_ = gtk_builder_get_object (self->priv->builder, "page_menu"); + _tmp1_ = _g_object_ref0 (GTK_MENU (_tmp0_)); + menu = _tmp1_; + _tmp2_ = gtk_get_current_event_time (); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, (guint) 3, _tmp2_); + _g_object_unref0 (menu); +} + + +void G_MODULE_EXPORT rotate_left_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + if (self->priv->updating_page_menu) { + return; + } + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + if (page != NULL) { + page_rotate_left (page); + } + _page_unref0 (page); +} + + +void G_MODULE_EXPORT rotate_right_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + if (self->priv->updating_page_menu) { + return; + } + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + if (page != NULL) { + page_rotate_right (page); + } + _page_unref0 (page); +} + + +static void simple_scan_set_crop (SimpleScan* self, const gchar* crop_name) { + Page* _tmp0_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->crop_rotate_menuitem, crop_name != NULL); + if (self->priv->updating_page_menu) { + return; + } + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + if (page == NULL) { + _page_unref0 (page); + return; + } + if (crop_name == NULL) { + page_set_no_crop (page); + _page_unref0 (page); + return; + } else { + if (g_strcmp0 (crop_name, "custom") == 0) { + gint _tmp1_; + gint width; + gint _tmp2_; + gint height; + gint crop_width; + gint crop_height; + _tmp1_ = page_get_width (page); + width = _tmp1_; + _tmp2_ = page_get_height (page); + height = _tmp2_; + crop_width = (gint) ((width * 0.8) + 0.5); + crop_height = (gint) ((height * 0.8) + 0.5); + page_set_custom_crop (page, crop_width, crop_height); + page_move_crop (page, (width - crop_width) / 2, (height - crop_height) / 2); + } else { + page_set_named_crop (page, crop_name); + } + } + _page_unref0 (page); +} + + +void G_MODULE_EXPORT no_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, NULL); + } +} + + +void G_MODULE_EXPORT custom_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "custom"); + } +} + + +void G_MODULE_EXPORT crop_toolbutton_toggled_cb (GtkToggleToolButton* widget, SimpleScan* self) { + GtkRadioMenuItem* menuitem = NULL; + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + if (self->priv->updating_page_menu) { + return; + } + _tmp0_ = gtk_toggle_tool_button_get_active (widget); + if (_tmp0_) { + GObject* _tmp1_ = NULL; + GtkRadioMenuItem* _tmp2_; + _tmp1_ = gtk_builder_get_object (self->priv->builder, "custom_crop_menuitem"); + _tmp2_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp1_)); + _g_object_unref0 (menuitem); + menuitem = _tmp2_; + } else { + GObject* _tmp3_ = NULL; + GtkRadioMenuItem* _tmp4_; + _tmp3_ = gtk_builder_get_object (self->priv->builder, "no_crop_menuitem"); + _tmp4_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp3_)); + _g_object_unref0 (menuitem); + menuitem = _tmp4_; + } + gtk_check_menu_item_set_active ((GtkCheckMenuItem*) menuitem, TRUE); + _g_object_unref0 (menuitem); +} + + +void G_MODULE_EXPORT four_by_six_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "4x6"); + } +} + + +void G_MODULE_EXPORT legal_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "legal"); + } +} + + +void G_MODULE_EXPORT letter_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "letter"); + } +} + + +void G_MODULE_EXPORT a6_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "A6"); + } +} + + +void G_MODULE_EXPORT a5_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "A5"); + } +} + + +void G_MODULE_EXPORT a4_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) { + gboolean _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_check_menu_item_get_active (widget); + if (_tmp0_) { + simple_scan_set_crop (self, "A4"); + } +} + + +void G_MODULE_EXPORT crop_rotate_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + if (page == NULL) { + _page_unref0 (page); + return; + } + page_rotate_crop (page); + _page_unref0 (page); +} + + +void G_MODULE_EXPORT page_move_left_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + guint _tmp1_; + guint index; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + _tmp1_ = book_get_page_index (self->priv->book, page); + index = _tmp1_; + if (index > ((guint) 0)) { + book_move_page (self->priv->book, page, index - 1); + } + simple_scan_update_page_menu (self); + _page_unref0 (page); +} + + +void G_MODULE_EXPORT page_move_right_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + Page* _tmp0_ = NULL; + Page* page; + guint _tmp1_; + guint index; + guint _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = book_view_get_selected (self->priv->book_view); + page = _tmp0_; + _tmp1_ = book_get_page_index (self->priv->book, page); + index = _tmp1_; + _tmp2_ = book_get_n_pages (self->priv->book); + if (index < (_tmp2_ - 1)) { + guint _tmp3_; + _tmp3_ = book_get_page_index (self->priv->book, page); + book_move_page (self->priv->book, page, _tmp3_ + 1); + } + simple_scan_update_page_menu (self); + _page_unref0 (page); +} + + +void G_MODULE_EXPORT page_delete_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + Book* _tmp0_ = NULL; + Book* _tmp1_; + Page* _tmp2_ = NULL; + Page* _tmp3_; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = book_view_get_book (self->priv->book_view); + _tmp1_ = _tmp0_; + _tmp2_ = book_view_get_selected (self->priv->book_view); + _tmp3_ = _tmp2_; + book_delete_page (_tmp1_, _tmp3_); + _page_unref0 (_tmp3_); + _book_unref0 (_tmp1_); +} + + +void G_MODULE_EXPORT save_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + simple_scan_save_document (self, FALSE); +} + + +void G_MODULE_EXPORT save_as_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + simple_scan_save_document (self, TRUE); +} + + +static gpointer _cairo_reference0 (gpointer self) { + return self ? cairo_reference (self) : NULL; +} + + +static void simple_scan_draw_page (SimpleScan* self, GtkPrintOperation* operation, GtkPrintContext* print_context, gint page_number) { + cairo_t* _tmp0_ = NULL; + cairo_t* _tmp1_; + cairo_t* context; + Page* _tmp2_ = NULL; + Page* page; + gboolean is_landscape; + gdouble _tmp3_; + gdouble _tmp4_; + gboolean _tmp5_; + gdouble _tmp7_; + gint _tmp8_; + gdouble _tmp9_; + gint _tmp10_; + GdkPixbuf* _tmp11_ = NULL; + GdkPixbuf* image; + g_return_if_fail (self != NULL); + g_return_if_fail (operation != NULL); + g_return_if_fail (print_context != NULL); + _tmp0_ = gtk_print_context_get_cairo_context (print_context); + _tmp1_ = _cairo_reference0 (_tmp0_); + context = _tmp1_; + _tmp2_ = book_get_page (self->priv->book, page_number); + page = _tmp2_; + is_landscape = FALSE; + _tmp3_ = gtk_print_context_get_width (print_context); + _tmp4_ = gtk_print_context_get_height (print_context); + if (_tmp3_ > _tmp4_) { + is_landscape = TRUE; + } + _tmp5_ = page_is_landscape (page); + if (_tmp5_ != is_landscape) { + gdouble _tmp6_; + _tmp6_ = gtk_print_context_get_width (print_context); + cairo_translate (context, _tmp6_, (gdouble) 0); + cairo_rotate (context, G_PI_2); + } + _tmp7_ = gtk_print_context_get_dpi_x (print_context); + _tmp8_ = page_get_dpi (page); + _tmp9_ = gtk_print_context_get_dpi_y (print_context); + _tmp10_ = page_get_dpi (page); + cairo_scale (context, _tmp7_ / _tmp8_, _tmp9_ / _tmp10_); + _tmp11_ = page_get_image (page, TRUE); + image = _tmp11_; + gdk_cairo_set_source_pixbuf (context, image, (gdouble) 0, (gdouble) 0); + cairo_paint (context); + _g_object_unref0 (image); + _page_unref0 (page); + _cairo_destroy0 (context); +} + + +void G_MODULE_EXPORT email_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + g_signal_emit_by_name (self, "email", self->priv->document_hint); +} + + +static void _simple_scan_draw_page_gtk_print_operation_draw_page (GtkPrintOperation* _sender, GtkPrintContext* context, gint page_nr, gpointer self) { + simple_scan_draw_page (self, _sender, context, page_nr); +} + + +void G_MODULE_EXPORT print_button_clicked_cb (GtkWidget* widget, SimpleScan* self) { + GtkPrintOperation* _tmp0_ = NULL; + GtkPrintOperation* print; + guint _tmp1_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = gtk_print_operation_new (); + print = _tmp0_; + _tmp1_ = book_get_n_pages (self->priv->book); + gtk_print_operation_set_n_pages (print, (gint) _tmp1_); + g_signal_connect (print, "draw-page", (GCallback) _simple_scan_draw_page_gtk_print_operation_draw_page, self); + { + gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, self->priv->window, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch14_g_error; + } + } + goto __finally14; + __catch14_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("ui.vala:1044: Error printing: %s", e->message); + _g_error_free0 (e); + } + __finally14: + if (_inner_error_ != NULL) { + _g_object_unref0 (print); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + _g_object_unref0 (print); +} + + +void G_MODULE_EXPORT help_contents_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + { + GdkScreen* _tmp0_ = NULL; + guint32 _tmp1_; + _tmp0_ = gtk_window_get_screen (self->priv->window); + _tmp1_ = gtk_get_current_event_time (); + gtk_show_uri (_tmp0_, "ghelp:simple-scan", _tmp1_, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch15_g_error; + } + } + goto __finally15; + __catch15_g_error: + { + GError* e = NULL; + const gchar* _tmp2_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + _tmp2_ = _ ("Unable to open help file"); + simple_scan_show_error_dialog (self, _tmp2_, e->message); + _g_error_free0 (e); + } + __finally15: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } +} + + +void G_MODULE_EXPORT about_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + gchar* _tmp0_; + gchar** _tmp1_ = NULL; + gchar** authors; + gint authors_length1; + gint _authors_size_; + const gchar* _tmp2_ = NULL; + gchar* _tmp3_; + gchar* license; + const gchar* _tmp4_ = NULL; + gchar* _tmp5_; + gchar* title; + const gchar* _tmp6_ = NULL; + gchar* _tmp7_; + gchar* description; + const gchar* _tmp8_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + _tmp0_ = g_strdup ("Robert Ancell <robert.ancell@canonical.com>"); + _tmp1_ = g_new0 (gchar*, 1 + 1); + _tmp1_[0] = _tmp0_; + authors = _tmp1_; + authors_length1 = 1; + _authors_size_ = authors_length1; + _tmp2_ = _ ("This program is free software: you can redistribute it and/or modify\n" \ +"it under the terms of the GNU General Public License as published by\n" \ +"the Free Software Foundation, either version 3 of the License, or\n" \ +"(at your option) any later version.\n" \ +"\n" \ +"This program is distributed in the hope that it will be useful,\n" \ +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \ +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \ +"GNU General Public License for more details.\n" \ +"\n" \ +"You should have received a copy of the GNU General Public License\n" \ +"along with this program. If not, see <http://www.gnu.org/licenses/>."); + _tmp3_ = g_strdup (_tmp2_); + license = _tmp3_; + _tmp4_ = _ ("About Simple Scan"); + _tmp5_ = g_strdup (_tmp4_); + title = _tmp5_; + _tmp6_ = _ ("Simple document scanning tool"); + _tmp7_ = g_strdup (_tmp6_); + description = _tmp7_; + _tmp8_ = _ ("translator-credits"); + gtk_show_about_dialog (self->priv->window, "title", title, "program-name", "Simple Scan", "version", VERSION, "comments", description, "logo-icon-name", "scanner", "authors", authors, "translator-credits", _tmp8_, "website", "https://launchpad.net/simple-scan", "copyright", "Copyright © 2009-2011 Canonical Ltd.", "license", license, "wrap-license", TRUE, NULL, NULL); + _g_free0 (description); + _g_free0 (title); + _g_free0 (license); + authors = (_vala_array_free (authors, authors_length1, (GDestroyNotify) g_free), NULL); +} + + +static gboolean simple_scan_on_quit (SimpleScan* self) { + gboolean result = FALSE; + const gchar* _tmp0_ = NULL; + const gchar* _tmp1_ = NULL; + gboolean _tmp2_; + gchar* _tmp3_ = NULL; + gchar* device; + gint paper_width; + gint paper_height; + gint _tmp4_; + gint _tmp5_; + gint _tmp6_; + gint _tmp7_; + ScanType _tmp8_; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = _ ("Save document before quitting?"); + _tmp1_ = _ ("Quit without Saving"); + _tmp2_ = simple_scan_prompt_to_save (self, _tmp0_, _tmp1_); + if (!_tmp2_) { + result = FALSE; + return result; + } + _tmp3_ = simple_scan_get_selected_device (self); + device = _tmp3_; + paper_width = 0; + paper_height = 0; + simple_scan_get_paper_size (self, &_tmp4_, &_tmp5_); + paper_width = _tmp4_; + paper_height = _tmp5_; + if (device != NULL) { + g_settings_set_string (self->priv->settings, "selected-device", device); + } + g_settings_set_string (self->priv->settings, "document-type", self->priv->document_hint); + _tmp6_ = simple_scan_get_text_dpi (self); + g_settings_set_int (self->priv->settings, "text-dpi", _tmp6_); + _tmp7_ = simple_scan_get_photo_dpi (self); + g_settings_set_int (self->priv->settings, "photo-dpi", _tmp7_); + _tmp8_ = simple_scan_get_page_side (self); + g_settings_set_enum (self->priv->settings, "page-side", (gint) _tmp8_); + g_settings_set_int (self->priv->settings, "paper-width", paper_width); + g_settings_set_int (self->priv->settings, "paper-height", paper_height); + g_settings_set_int (self->priv->settings, "window-width", self->priv->window_width); + g_settings_set_int (self->priv->settings, "window-height", self->priv->window_height); + g_settings_set_boolean (self->priv->settings, "window-is-maximized", self->priv->window_is_maximized); + g_settings_set_enum (self->priv->settings, "scan-direction", (gint) self->priv->default_page_scan_direction); + g_settings_set_int (self->priv->settings, "page-width", self->priv->default_page_width); + g_settings_set_int (self->priv->settings, "page-height", self->priv->default_page_height); + g_settings_set_int (self->priv->settings, "page-dpi", self->priv->default_page_dpi); + g_signal_emit_by_name (self, "quit"); + result = TRUE; + _g_free0 (device); + return result; +} + + +void G_MODULE_EXPORT quit_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + simple_scan_on_quit (self); +} + + +gboolean G_MODULE_EXPORT simple_scan_window_configure_event_cb (GtkWidget* widget, GdkEventConfigure* event, SimpleScan* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + if (!self->priv->window_is_maximized) { + self->priv->window_width = (*event).width; + self->priv->window_height = (*event).height; + } + result = FALSE; + return result; +} + + +static void simple_scan_info_bar_response_cb (SimpleScan* self, GtkInfoBar* widget, gint response_id) { + g_return_if_fail (self != NULL); + g_return_if_fail (widget != NULL); + if (response_id == 1) { + gtk_widget_grab_focus ((GtkWidget*) self->priv->device_combo); + gtk_window_present ((GtkWindow*) self->priv->preferences_dialog); + } else { + self->priv->have_error = FALSE; + _g_free0 (self->priv->error_title); + self->priv->error_title = NULL; + _g_free0 (self->priv->error_text); + self->priv->error_text = NULL; + simple_scan_update_info_bar (self); + } +} + + +gboolean G_MODULE_EXPORT simple_scan_window_window_state_event_cb (GtkWidget* widget, GdkEventWindowState* event, SimpleScan* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + if (((*event).changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0) { + self->priv->window_is_maximized = ((*event).new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0; + } + result = FALSE; + return result; +} + + +gboolean G_MODULE_EXPORT window_delete_event_cb (GtkWidget* widget, GdkEvent* event, SimpleScan* self) { + gboolean result = FALSE; + gboolean _tmp0_; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (event != NULL, FALSE); + _tmp0_ = simple_scan_on_quit (self); + result = !_tmp0_; + return result; +} + + +static void simple_scan_page_size_changed_cb (SimpleScan* self, Page* page) { + gint _tmp0_; + gint _tmp1_; + gint _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = page_get_width (page); + self->priv->default_page_width = _tmp0_; + _tmp1_ = page_get_height (page); + self->priv->default_page_height = _tmp1_; + _tmp2_ = page_get_dpi (page); + self->priv->default_page_dpi = _tmp2_; +} + + +static void simple_scan_page_scan_direction_changed_cb (SimpleScan* self, Page* page) { + ScanDirection _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = page_get_scan_direction (page); + self->priv->default_page_scan_direction = _tmp0_; +} + + +static void _simple_scan_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self) { + simple_scan_page_size_changed_cb (self, _sender); +} + + +static void _simple_scan_page_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self) { + simple_scan_page_scan_direction_changed_cb (self, _sender); +} + + +static void simple_scan_page_added_cb (SimpleScan* self, Book* book, Page* page) { + gint _tmp0_; + gint _tmp1_; + gint _tmp2_; + ScanDirection _tmp3_; + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = page_get_width (page); + self->priv->default_page_width = _tmp0_; + _tmp1_ = page_get_height (page); + self->priv->default_page_height = _tmp1_; + _tmp2_ = page_get_dpi (page); + self->priv->default_page_dpi = _tmp2_; + _tmp3_ = page_get_scan_direction (page); + self->priv->default_page_scan_direction = _tmp3_; + g_signal_connect (page, "size-changed", (GCallback) _simple_scan_page_size_changed_cb_page_size_changed, self); + g_signal_connect (page, "scan-direction-changed", (GCallback) _simple_scan_page_scan_direction_changed_cb_page_scan_direction_changed, self); + simple_scan_update_page_menu (self); +} + + +static void simple_scan_page_removed_cb (SimpleScan* self, Book* book, Page* page) { + guint _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + g_return_if_fail (page != NULL); + _tmp0_ = book_get_n_pages (book); + if (_tmp0_ == ((guint) 1)) { + simple_scan_add_default_page (self); + } + simple_scan_update_page_menu (self); +} + + +static void simple_scan_set_dpi_combo (SimpleScan* self, GtkComboBox* combo, gint default_dpi, gint current_dpi) { + GtkCellRendererText* _tmp0_ = NULL; + GtkCellRendererText* renderer; + GtkTreeModel* _tmp1_ = NULL; + GtkListStore* _tmp2_; + GtkListStore* model; + gint* _tmp3_ = NULL; + gint* scan_resolutions; + gint scan_resolutions_length1; + gint _scan_resolutions_size_; + g_return_if_fail (self != NULL); + g_return_if_fail (combo != NULL); + _tmp0_ = (GtkCellRendererText*) gtk_cell_renderer_text_new (); + renderer = g_object_ref_sink (_tmp0_); + gtk_cell_layout_pack_start ((GtkCellLayout*) combo, (GtkCellRenderer*) renderer, TRUE); + gtk_cell_layout_add_attribute ((GtkCellLayout*) combo, (GtkCellRenderer*) renderer, "text", 1); + _tmp1_ = gtk_combo_box_get_model (combo); + _tmp2_ = _g_object_ref0 (GTK_LIST_STORE (_tmp1_)); + model = _tmp2_; + _tmp3_ = g_new0 (gint, 6); + _tmp3_[0] = 75; + _tmp3_[1] = 150; + _tmp3_[2] = 300; + _tmp3_[3] = 600; + _tmp3_[4] = 1200; + _tmp3_[5] = 2400; + scan_resolutions = _tmp3_; + scan_resolutions_length1 = 6; + _scan_resolutions_size_ = scan_resolutions_length1; + { + gint* dpi_collection = NULL; + gint dpi_collection_length1 = 0; + gint _dpi_collection_size_ = 0; + gint dpi_it; + dpi_collection = scan_resolutions; + dpi_collection_length1 = scan_resolutions_length1; + for (dpi_it = 0; dpi_it < scan_resolutions_length1; dpi_it = dpi_it + 1) { + gint dpi = 0; + dpi = dpi_collection[dpi_it]; + { + gchar* label = NULL; + GtkTreeIter iter = {0}; + GtkTreeIter _tmp12_ = {0}; + if (dpi == default_dpi) { + const gchar* _tmp4_ = NULL; + gchar* _tmp5_ = NULL; + _tmp4_ = _ ("%d dpi (default)"); + _tmp5_ = g_strdup_printf (_tmp4_, dpi); + _g_free0 (label); + label = _tmp5_; + } else { + if (dpi == 75) { + const gchar* _tmp6_ = NULL; + gchar* _tmp7_ = NULL; + _tmp6_ = _ ("%d dpi (draft)"); + _tmp7_ = g_strdup_printf (_tmp6_, dpi); + _g_free0 (label); + label = _tmp7_; + } else { + if (dpi == 1200) { + const gchar* _tmp8_ = NULL; + gchar* _tmp9_ = NULL; + _tmp8_ = _ ("%d dpi (high resolution)"); + _tmp9_ = g_strdup_printf (_tmp8_, dpi); + _g_free0 (label); + label = _tmp9_; + } else { + const gchar* _tmp10_ = NULL; + gchar* _tmp11_ = NULL; + _tmp10_ = _ ("%d dpi"); + _tmp11_ = g_strdup_printf (_tmp10_, dpi); + _g_free0 (label); + label = _tmp11_; + } + } + } + gtk_list_store_append (model, &_tmp12_); + iter = _tmp12_; + gtk_list_store_set (model, &iter, 0, dpi, 1, label, -1, -1); + if (dpi == current_dpi) { + gtk_combo_box_set_active_iter (combo, &iter); + } + _g_free0 (label); + } + } + } + scan_resolutions = (g_free (scan_resolutions), NULL); + _g_object_unref0 (model); + _g_object_unref0 (renderer); +} + + +static void simple_scan_needs_saving_cb (SimpleScan* self, Book* book) { + gboolean _tmp0_; + gboolean _tmp1_; + gboolean _tmp2_; + g_return_if_fail (self != NULL); + g_return_if_fail (book != NULL); + _tmp0_ = book_get_needs_saving (book); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_menuitem, _tmp0_); + _tmp1_ = book_get_needs_saving (book); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_toolbutton, _tmp1_); + _tmp2_ = book_get_needs_saving (book); + if (_tmp2_) { + gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_as_menuitem, TRUE); + } +} + + +static void _simple_scan_info_bar_response_cb_gtk_info_bar_response (GtkInfoBar* _sender, gint response_id, gpointer self) { + simple_scan_info_bar_response_cb (self, _sender, response_id); +} + + +static void _simple_scan_page_selected_cb_book_view_page_selected (BookView* _sender, Page* page, gpointer self) { + simple_scan_page_selected_cb (self, _sender, page); +} + + +static void _simple_scan_show_page_cb_book_view_show_page (BookView* _sender, Page* page, gpointer self) { + simple_scan_show_page_cb (self, _sender, page); +} + + +static void _simple_scan_show_page_menu_cb_book_view_show_menu (BookView* _sender, gpointer self) { + simple_scan_show_page_menu_cb (self, _sender); +} + + +static void _simple_scan_needs_saving_cb_book_needs_saving_changed (Book* _sender, gpointer self) { + simple_scan_needs_saving_cb (self, _sender); +} + + +static void simple_scan_load (SimpleScan* self) { + GtkIconTheme* _tmp0_ = NULL; + GtkBuilder* _tmp1_ = NULL; + gchar* _tmp2_ = NULL; + gchar* filename; + GObject* _tmp5_ = NULL; + GtkWindow* _tmp6_; + GObject* _tmp7_ = NULL; + GtkVBox* _tmp8_; + GObject* _tmp9_ = NULL; + GtkMenuItem* _tmp10_; + GObject* _tmp11_ = NULL; + GtkMenuItem* _tmp12_; + GObject* _tmp13_ = NULL; + GtkMenuItem* _tmp14_; + GObject* _tmp15_ = NULL; + GtkMenuItem* _tmp16_; + GObject* _tmp17_ = NULL; + GtkMenuItem* _tmp18_; + GObject* _tmp19_ = NULL; + GtkMenuItem* _tmp20_; + GObject* _tmp21_ = NULL; + GtkToolButton* _tmp22_; + GObject* _tmp23_ = NULL; + GtkMenuItem* _tmp24_; + GObject* _tmp25_ = NULL; + GtkToolButton* _tmp26_; + GObject* _tmp27_ = NULL; + GtkRadioMenuItem* _tmp28_; + GObject* _tmp29_ = NULL; + GtkRadioMenuItem* _tmp30_; + GObject* _tmp31_ = NULL; + GtkRadioMenuItem* _tmp32_; + GObject* _tmp33_ = NULL; + GtkRadioMenuItem* _tmp34_; + GObject* _tmp35_ = NULL; + GtkDialog* _tmp36_; + GObject* _tmp37_ = NULL; + GtkLabel* _tmp38_; + GObject* _tmp39_ = NULL; + GtkEntry* _tmp40_; + GObject* _tmp41_ = NULL; + GtkEntry* _tmp42_; + GObject* _tmp43_ = NULL; + GtkDialog* _tmp44_; + GObject* _tmp45_ = NULL; + GtkComboBox* _tmp46_; + GtkTreeModel* _tmp47_ = NULL; + GtkListStore* _tmp48_; + GObject* _tmp49_ = NULL; + GtkComboBox* _tmp50_; + GtkTreeModel* _tmp51_ = NULL; + GtkListStore* _tmp52_; + GObject* _tmp53_ = NULL; + GtkComboBox* _tmp54_; + GtkTreeModel* _tmp55_ = NULL; + GtkListStore* _tmp56_; + GObject* _tmp57_ = NULL; + GtkComboBox* _tmp58_; + GtkTreeModel* _tmp59_ = NULL; + GtkListStore* _tmp60_; + GObject* _tmp61_ = NULL; + GtkComboBox* _tmp62_; + GtkTreeModel* _tmp63_ = NULL; + GtkListStore* _tmp64_; + GtkInfoBar* _tmp65_ = NULL; + GtkHBox* _tmp66_ = NULL; + GtkHBox* hbox; + GtkWidget* _tmp67_ = NULL; + GtkContainer* _tmp68_; + GtkContainer* content_area; + GtkImage* _tmp69_ = NULL; + GtkLabel* _tmp70_ = NULL; + GtkWidget* _tmp71_ = NULL; + GtkButton* _tmp72_; + const gchar* _tmp73_ = NULL; + GtkWidget* _tmp74_ = NULL; + GtkButton* _tmp75_; + GtkTreeIter iter = {0}; + GtkTreeIter _tmp76_ = {0}; + const gchar* _tmp77_ = NULL; + GtkTreeIter _tmp78_ = {0}; + GtkTreeIter _tmp79_ = {0}; + GtkTreeIter _tmp80_ = {0}; + GtkTreeIter _tmp81_ = {0}; + GtkTreeIter _tmp82_ = {0}; + GtkTreeIter _tmp83_ = {0}; + gint _tmp84_; + gint dpi; + gint _tmp85_; + GtkCellRendererText* _tmp86_ = NULL; + GtkCellRendererText* renderer; + GtkCellRendererText* _tmp87_ = NULL; + gint _tmp88_; + GtkCellRendererText* _tmp89_ = NULL; + gint _tmp90_; + gint paper_width; + gint _tmp91_; + gint paper_height; + gchar* _tmp92_ = NULL; + gchar* device; + gchar* _tmp95_ = NULL; + gchar* document_type; + BookView* _tmp96_ = NULL; + gint _tmp97_; + gint _tmp98_; + gint _tmp99_; + gint _tmp100_; + gint _tmp101_; + gint _tmp102_; + gboolean _tmp103_; + guint _tmp104_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = gtk_icon_theme_get_default (); + gtk_icon_theme_append_search_path (_tmp0_, ICON_DIR); + gtk_window_set_default_icon_name ("scanner"); + _tmp1_ = gtk_builder_new (); + _g_object_unref0 (self->priv->builder); + self->priv->builder = _tmp1_; + _tmp2_ = g_build_filename (UI_DIR, "simple-scan.ui", NULL, NULL); + filename = _tmp2_; + { + gtk_builder_add_from_file (self->priv->builder, filename, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch16_g_error; + } + } + goto __finally16; + __catch16_g_error: + { + GError* e = NULL; + const gchar* _tmp3_ = NULL; + const gchar* _tmp4_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_critical ("ui.vala:1261: Unable to load UI %s: %s\n", filename, e->message); + _tmp3_ = _ ("Files missing"); + _tmp4_ = _ ("Please check your installation"); + simple_scan_show_error_dialog (self, _tmp3_, _tmp4_); + exit (EXIT_FAILURE); + _g_error_free0 (e); + } + __finally16: + if (_inner_error_ != NULL) { + _g_free0 (filename); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + gtk_builder_connect_signals (self->priv->builder, self); + _tmp5_ = gtk_builder_get_object (self->priv->builder, "simple_scan_window"); + _tmp6_ = _g_object_ref0 (GTK_WINDOW (_tmp5_)); + _g_object_unref0 (self->priv->window); + self->priv->window = _tmp6_; + _tmp7_ = gtk_builder_get_object (self->priv->builder, "main_vbox"); + _tmp8_ = _g_object_ref0 (GTK_VBOX (_tmp7_)); + _g_object_unref0 (self->priv->main_vbox); + self->priv->main_vbox = _tmp8_; + _tmp9_ = gtk_builder_get_object (self->priv->builder, "page_move_left_menuitem"); + _tmp10_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp9_)); + _g_object_unref0 (self->priv->page_move_left_menuitem); + self->priv->page_move_left_menuitem = _tmp10_; + _tmp11_ = gtk_builder_get_object (self->priv->builder, "page_move_right_menuitem"); + _tmp12_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp11_)); + _g_object_unref0 (self->priv->page_move_right_menuitem); + self->priv->page_move_right_menuitem = _tmp12_; + _tmp13_ = gtk_builder_get_object (self->priv->builder, "page_delete_menuitem"); + _tmp14_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp13_)); + _g_object_unref0 (self->priv->page_delete_menuitem); + self->priv->page_delete_menuitem = _tmp14_; + _tmp15_ = gtk_builder_get_object (self->priv->builder, "crop_rotate_menuitem"); + _tmp16_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp15_)); + _g_object_unref0 (self->priv->crop_rotate_menuitem); + self->priv->crop_rotate_menuitem = _tmp16_; + _tmp17_ = gtk_builder_get_object (self->priv->builder, "save_menuitem"); + _tmp18_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp17_)); + _g_object_unref0 (self->priv->save_menuitem); + self->priv->save_menuitem = _tmp18_; + _tmp19_ = gtk_builder_get_object (self->priv->builder, "save_as_menuitem"); + _tmp20_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp19_)); + _g_object_unref0 (self->priv->save_as_menuitem); + self->priv->save_as_menuitem = _tmp20_; + _tmp21_ = gtk_builder_get_object (self->priv->builder, "save_toolbutton"); + _tmp22_ = _g_object_ref0 (GTK_TOOL_BUTTON (_tmp21_)); + _g_object_unref0 (self->priv->save_toolbutton); + self->priv->save_toolbutton = _tmp22_; + _tmp23_ = gtk_builder_get_object (self->priv->builder, "stop_scan_menuitem"); + _tmp24_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp23_)); + _g_object_unref0 (self->priv->stop_menuitem); + self->priv->stop_menuitem = _tmp24_; + _tmp25_ = gtk_builder_get_object (self->priv->builder, "stop_toolbutton"); + _tmp26_ = _g_object_ref0 (GTK_TOOL_BUTTON (_tmp25_)); + _g_object_unref0 (self->priv->stop_toolbutton); + self->priv->stop_toolbutton = _tmp26_; + _tmp27_ = gtk_builder_get_object (self->priv->builder, "text_toolbutton_menuitem"); + _tmp28_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp27_)); + _g_object_unref0 (self->priv->text_toolbar_menuitem); + self->priv->text_toolbar_menuitem = _tmp28_; + _tmp29_ = gtk_builder_get_object (self->priv->builder, "text_menuitem"); + _tmp30_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp29_)); + _g_object_unref0 (self->priv->text_menu_menuitem); + self->priv->text_menu_menuitem = _tmp30_; + _tmp31_ = gtk_builder_get_object (self->priv->builder, "photo_toolbutton_menuitem"); + _tmp32_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp31_)); + _g_object_unref0 (self->priv->photo_toolbar_menuitem); + self->priv->photo_toolbar_menuitem = _tmp32_; + _tmp33_ = gtk_builder_get_object (self->priv->builder, "photo_menuitem"); + _tmp34_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp33_)); + _g_object_unref0 (self->priv->photo_menu_menuitem); + self->priv->photo_menu_menuitem = _tmp34_; + _tmp35_ = gtk_builder_get_object (self->priv->builder, "authorize_dialog"); + _tmp36_ = _g_object_ref0 (GTK_DIALOG (_tmp35_)); + _g_object_unref0 (self->priv->authorize_dialog); + self->priv->authorize_dialog = _tmp36_; + _tmp37_ = gtk_builder_get_object (self->priv->builder, "authorize_label"); + _tmp38_ = _g_object_ref0 (GTK_LABEL (_tmp37_)); + _g_object_unref0 (self->priv->authorize_label); + self->priv->authorize_label = _tmp38_; + _tmp39_ = gtk_builder_get_object (self->priv->builder, "username_entry"); + _tmp40_ = _g_object_ref0 (GTK_ENTRY (_tmp39_)); + _g_object_unref0 (self->priv->username_entry); + self->priv->username_entry = _tmp40_; + _tmp41_ = gtk_builder_get_object (self->priv->builder, "password_entry"); + _tmp42_ = _g_object_ref0 (GTK_ENTRY (_tmp41_)); + _g_object_unref0 (self->priv->password_entry); + self->priv->password_entry = _tmp42_; + _tmp43_ = gtk_builder_get_object (self->priv->builder, "preferences_dialog"); + _tmp44_ = _g_object_ref0 (GTK_DIALOG (_tmp43_)); + _g_object_unref0 (self->priv->preferences_dialog); + self->priv->preferences_dialog = _tmp44_; + _tmp45_ = gtk_builder_get_object (self->priv->builder, "device_combo"); + _tmp46_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp45_)); + _g_object_unref0 (self->priv->device_combo); + self->priv->device_combo = _tmp46_; + _tmp47_ = gtk_combo_box_get_model (self->priv->device_combo); + _tmp48_ = _g_object_ref0 (GTK_LIST_STORE (_tmp47_)); + _g_object_unref0 (self->priv->device_model); + self->priv->device_model = _tmp48_; + _tmp49_ = gtk_builder_get_object (self->priv->builder, "text_dpi_combo"); + _tmp50_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp49_)); + _g_object_unref0 (self->priv->text_dpi_combo); + self->priv->text_dpi_combo = _tmp50_; + _tmp51_ = gtk_combo_box_get_model (self->priv->text_dpi_combo); + _tmp52_ = _g_object_ref0 (GTK_LIST_STORE (_tmp51_)); + _g_object_unref0 (self->priv->text_dpi_model); + self->priv->text_dpi_model = _tmp52_; + _tmp53_ = gtk_builder_get_object (self->priv->builder, "photo_dpi_combo"); + _tmp54_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp53_)); + _g_object_unref0 (self->priv->photo_dpi_combo); + self->priv->photo_dpi_combo = _tmp54_; + _tmp55_ = gtk_combo_box_get_model (self->priv->photo_dpi_combo); + _tmp56_ = _g_object_ref0 (GTK_LIST_STORE (_tmp55_)); + _g_object_unref0 (self->priv->photo_dpi_model); + self->priv->photo_dpi_model = _tmp56_; + _tmp57_ = gtk_builder_get_object (self->priv->builder, "page_side_combo"); + _tmp58_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp57_)); + _g_object_unref0 (self->priv->page_side_combo); + self->priv->page_side_combo = _tmp58_; + _tmp59_ = gtk_combo_box_get_model (self->priv->page_side_combo); + _tmp60_ = _g_object_ref0 (GTK_LIST_STORE (_tmp59_)); + _g_object_unref0 (self->priv->page_side_model); + self->priv->page_side_model = _tmp60_; + _tmp61_ = gtk_builder_get_object (self->priv->builder, "paper_size_combo"); + _tmp62_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp61_)); + _g_object_unref0 (self->priv->paper_size_combo); + self->priv->paper_size_combo = _tmp62_; + _tmp63_ = gtk_combo_box_get_model (self->priv->paper_size_combo); + _tmp64_ = _g_object_ref0 (GTK_LIST_STORE (_tmp63_)); + _g_object_unref0 (self->priv->paper_size_model); + self->priv->paper_size_model = _tmp64_; + _tmp65_ = (GtkInfoBar*) gtk_info_bar_new (); + _g_object_unref0 (self->priv->info_bar); + self->priv->info_bar = g_object_ref_sink (_tmp65_); + g_signal_connect (self->priv->info_bar, "response", (GCallback) _simple_scan_info_bar_response_cb_gtk_info_bar_response, self); + gtk_box_pack_start ((GtkBox*) self->priv->main_vbox, (GtkWidget*) self->priv->info_bar, FALSE, TRUE, (guint) 0); + _tmp66_ = (GtkHBox*) gtk_hbox_new (FALSE, 12); + hbox = g_object_ref_sink (_tmp66_); + _tmp67_ = gtk_info_bar_get_content_area (self->priv->info_bar); + _tmp68_ = _g_object_ref0 (GTK_CONTAINER (_tmp67_)); + content_area = _tmp68_; + gtk_container_add (content_area, (GtkWidget*) hbox); + gtk_widget_show ((GtkWidget*) hbox); + _tmp69_ = (GtkImage*) gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); + _g_object_unref0 (self->priv->info_bar_image); + self->priv->info_bar_image = g_object_ref_sink (_tmp69_); + gtk_box_pack_start ((GtkBox*) hbox, (GtkWidget*) self->priv->info_bar_image, FALSE, TRUE, (guint) 0); + gtk_widget_show ((GtkWidget*) self->priv->info_bar_image); + _tmp70_ = (GtkLabel*) gtk_label_new (NULL); + _g_object_unref0 (self->priv->info_bar_label); + self->priv->info_bar_label = g_object_ref_sink (_tmp70_); + gtk_misc_set_alignment ((GtkMisc*) self->priv->info_bar_label, 0.0f, 0.5f); + gtk_box_pack_start ((GtkBox*) hbox, (GtkWidget*) self->priv->info_bar_label, TRUE, TRUE, (guint) 0); + gtk_widget_show ((GtkWidget*) self->priv->info_bar_label); + _tmp71_ = gtk_info_bar_add_button (self->priv->info_bar, GTK_STOCK_CLOSE, (gint) GTK_RESPONSE_CLOSE); + _tmp72_ = _g_object_ref0 (GTK_BUTTON (_tmp71_)); + _g_object_unref0 (self->priv->info_bar_close_button); + self->priv->info_bar_close_button = _tmp72_; + _tmp73_ = _ ("Change _Scanner"); + _tmp74_ = gtk_info_bar_add_button (self->priv->info_bar, _tmp73_, 1); + _tmp75_ = _g_object_ref0 (GTK_BUTTON (_tmp74_)); + _g_object_unref0 (self->priv->info_bar_change_scanner_button); + self->priv->info_bar_change_scanner_button = _tmp75_; + gtk_list_store_append (self->priv->paper_size_model, &_tmp76_); + iter = _tmp76_; + _tmp77_ = _ ("Automatic"); + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 0, 1, 0, 2, _tmp77_, -1, -1); + gtk_list_store_append (self->priv->paper_size_model, &_tmp78_); + iter = _tmp78_; + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 1050, 1, 1480, 2, "A6", -1, -1); + gtk_list_store_append (self->priv->paper_size_model, &_tmp79_); + iter = _tmp79_; + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 1480, 1, 2100, 2, "A5", -1, -1); + gtk_list_store_append (self->priv->paper_size_model, &_tmp80_); + iter = _tmp80_; + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 2100, 1, 2970, 2, "A4", -1, -1); + gtk_list_store_append (self->priv->paper_size_model, &_tmp81_); + iter = _tmp81_; + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 2159, 1, 2794, 2, "Letter", -1, -1); + gtk_list_store_append (self->priv->paper_size_model, &_tmp82_); + iter = _tmp82_; + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 2159, 1, 3556, 2, "Legal", -1, -1); + gtk_list_store_append (self->priv->paper_size_model, &_tmp83_); + iter = _tmp83_; + gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 1016, 1, 1524, 2, "4×6", -1, -1); + _tmp84_ = g_settings_get_int (self->priv->settings, "text-dpi"); + dpi = _tmp84_; + if (dpi <= 0) { + dpi = SIMPLE_SCAN_DEFAULT_TEXT_DPI; + } + simple_scan_set_dpi_combo (self, self->priv->text_dpi_combo, SIMPLE_SCAN_DEFAULT_TEXT_DPI, dpi); + _tmp85_ = g_settings_get_int (self->priv->settings, "photo-dpi"); + dpi = _tmp85_; + if (dpi <= 0) { + dpi = SIMPLE_SCAN_DEFAULT_PHOTO_DPI; + } + simple_scan_set_dpi_combo (self, self->priv->photo_dpi_combo, SIMPLE_SCAN_DEFAULT_PHOTO_DPI, dpi); + _tmp86_ = (GtkCellRendererText*) gtk_cell_renderer_text_new (); + renderer = g_object_ref_sink (_tmp86_); + gtk_cell_layout_pack_start ((GtkCellLayout*) self->priv->device_combo, (GtkCellRenderer*) renderer, TRUE); + gtk_cell_layout_add_attribute ((GtkCellLayout*) self->priv->device_combo, (GtkCellRenderer*) renderer, "text", 1); + _tmp87_ = (GtkCellRendererText*) gtk_cell_renderer_text_new (); + _g_object_unref0 (renderer); + renderer = g_object_ref_sink (_tmp87_); + gtk_cell_layout_pack_start ((GtkCellLayout*) self->priv->page_side_combo, (GtkCellRenderer*) renderer, TRUE); + gtk_cell_layout_add_attribute ((GtkCellLayout*) self->priv->page_side_combo, (GtkCellRenderer*) renderer, "text", 1); + _tmp88_ = g_settings_get_enum (self->priv->settings, "page-side"); + simple_scan_set_page_side (self, (ScanType) _tmp88_); + _tmp89_ = (GtkCellRendererText*) gtk_cell_renderer_text_new (); + _g_object_unref0 (renderer); + renderer = g_object_ref_sink (_tmp89_); + gtk_cell_layout_pack_start ((GtkCellLayout*) self->priv->paper_size_combo, (GtkCellRenderer*) renderer, TRUE); + gtk_cell_layout_add_attribute ((GtkCellLayout*) self->priv->paper_size_combo, (GtkCellRenderer*) renderer, "text", 2); + _tmp90_ = g_settings_get_int (self->priv->settings, "paper-width"); + paper_width = _tmp90_; + _tmp91_ = g_settings_get_int (self->priv->settings, "paper-height"); + paper_height = _tmp91_; + simple_scan_set_paper_size (self, paper_width, paper_height); + _tmp92_ = g_settings_get_string (self->priv->settings, "selected-device"); + device = _tmp92_; + if (device != NULL) { + GtkTreeIter _tmp93_ = {0}; + gboolean _tmp94_; + _tmp94_ = simple_scan_find_scan_device (self, device, &_tmp93_); + iter = _tmp93_; + if (_tmp94_) { + gtk_combo_box_set_active_iter (self->priv->device_combo, &iter); + } + } + _tmp95_ = g_settings_get_string (self->priv->settings, "document-type"); + document_type = _tmp95_; + if (document_type != NULL) { + simple_scan_set_document_hint (self, document_type); + } + _tmp96_ = book_view_new (self->priv->book); + _g_object_unref0 (self->priv->book_view); + self->priv->book_view = g_object_ref_sink (_tmp96_); + gtk_container_set_border_width ((GtkContainer*) self->priv->book_view, (guint) 18); + gtk_box_pack_end ((GtkBox*) self->priv->main_vbox, (GtkWidget*) self->priv->book_view, TRUE, TRUE, (guint) 0); + g_signal_connect (self->priv->book_view, "page-selected", (GCallback) _simple_scan_page_selected_cb_book_view_page_selected, self); + g_signal_connect (self->priv->book_view, "show-page", (GCallback) _simple_scan_show_page_cb_book_view_show_page, self); + g_signal_connect (self->priv->book_view, "show-menu", (GCallback) _simple_scan_show_page_menu_cb_book_view_show_menu, self); + gtk_widget_show ((GtkWidget*) self->priv->book_view); + _tmp97_ = g_settings_get_enum (self->priv->settings, "scan-direction"); + self->priv->default_page_scan_direction = (ScanDirection) _tmp97_; + _tmp98_ = g_settings_get_int (self->priv->settings, "page-width"); + self->priv->default_page_width = _tmp98_; + if (self->priv->default_page_width <= 0) { + self->priv->default_page_width = 595; + } + _tmp99_ = g_settings_get_int (self->priv->settings, "page-height"); + self->priv->default_page_height = _tmp99_; + if (self->priv->default_page_height <= 0) { + self->priv->default_page_height = 842; + } + _tmp100_ = g_settings_get_int (self->priv->settings, "page-dpi"); + self->priv->default_page_dpi = _tmp100_; + if (self->priv->default_page_dpi <= 0) { + self->priv->default_page_dpi = 72; + } + _tmp101_ = g_settings_get_int (self->priv->settings, "window-width"); + self->priv->window_width = _tmp101_; + if (self->priv->window_width <= 0) { + self->priv->window_width = 600; + } + _tmp102_ = g_settings_get_int (self->priv->settings, "window-height"); + self->priv->window_height = _tmp102_; + if (self->priv->window_height <= 0) { + self->priv->window_height = 400; + } + g_debug ("ui.vala:1407: Restoring window to %dx%d pixels", self->priv->window_width, self->priv->window_height); + gtk_window_set_default_size (self->priv->window, self->priv->window_width, self->priv->window_height); + _tmp103_ = g_settings_get_boolean (self->priv->settings, "window-is-maximized"); + self->priv->window_is_maximized = _tmp103_; + if (self->priv->window_is_maximized) { + g_debug ("ui.vala:1412: Restoring window to maximized"); + gtk_window_maximize (self->priv->window); + } + _tmp104_ = book_get_n_pages (self->priv->book); + if (_tmp104_ == ((guint) 0)) { + simple_scan_add_default_page (self); + } + book_set_needs_saving (self->priv->book, FALSE); + g_signal_connect (self->priv->book, "needs-saving-changed", (GCallback) _simple_scan_needs_saving_cb_book_needs_saving_changed, self); + _g_free0 (document_type); + _g_free0 (device); + _g_object_unref0 (renderer); + _g_object_unref0 (content_area); + _g_object_unref0 (hbox); + _g_free0 (filename); +} + + +static gpointer _book_ref0 (gpointer self) { + return self ? book_ref (self) : NULL; +} + + +Book* simple_scan_get_book (SimpleScan* self) { + Book* result = NULL; + Book* _tmp0_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = _book_ref0 (self->priv->book); + result = _tmp0_; + return result; +} + + +void simple_scan_set_selected_page (SimpleScan* self, Page* page) { + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + book_view_select_page (self->priv->book_view, page); +} + + +Page* simple_scan_get_selected_page (SimpleScan* self) { + Page* result = NULL; + Page* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = book_view_get_selected (self->priv->book_view); + result = _tmp0_; + return result; +} + + +void simple_scan_set_scanning (SimpleScan* self, gboolean scanning) { + g_return_if_fail (self != NULL); + self->priv->scanning = scanning; + gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_delete_menuitem, !scanning); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->stop_menuitem, scanning); + gtk_widget_set_sensitive ((GtkWidget*) self->priv->stop_toolbutton, scanning); +} + + +void simple_scan_show_error (SimpleScan* self, const gchar* error_title, const gchar* error_text, gboolean change_scanner_hint) { + gchar* _tmp0_; + gchar* _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (error_title != NULL); + g_return_if_fail (error_text != NULL); + self->priv->have_error = TRUE; + _tmp0_ = g_strdup (error_title); + _g_free0 (self->priv->error_title); + self->priv->error_title = _tmp0_; + _tmp1_ = g_strdup (error_text); + _g_free0 (self->priv->error_text); + self->priv->error_text = _tmp1_; + self->priv->error_change_scanner_hint = change_scanner_hint; + simple_scan_update_info_bar (self); +} + - update_page_menu (ui); +void simple_scan_start (SimpleScan* self) { + g_return_if_fail (self != NULL); + gtk_widget_show ((GtkWidget*) self->priv->window); } -void page_move_right_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -page_move_right_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - Book *book = book_view_get_book (ui->priv->book_view); - Page *page = book_view_get_selected (ui->priv->book_view); - gint index; - - index = book_get_page_index (book, page); - if (index < book_get_n_pages (book) - 1) - book_move_page (book, page, book_get_page_index (book, page) + 1); - - update_page_menu (ui); +static void g_cclosure_user_marshal_VOID__STRING_SCAN_OPTIONS (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__STRING_SCAN_OPTIONS) (gpointer data1, const char* arg_1, gpointer arg_2, gpointer data2); + register GMarshalFunc_VOID__STRING_SCAN_OPTIONS callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 3); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_SCAN_OPTIONS) (marshal_data ? marshal_data : cc->callback); + callback (data1, g_value_get_string (param_values + 1), value_get_scan_options (param_values + 2), data2); } -void page_delete_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -page_delete_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - book_delete_page (book_view_get_book (ui->priv->book_view), - book_view_get_selected (ui->priv->book_view)); +static void value_simple_scan_init (GValue* value) { + value->data[0].v_pointer = NULL; } -void save_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -save_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - save_document (ui, FALSE); +static void value_simple_scan_free_value (GValue* value) { + if (value->data[0].v_pointer) { + simple_scan_unref (value->data[0].v_pointer); + } } -void save_as_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -save_as_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - save_document (ui, TRUE); +static void value_simple_scan_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = simple_scan_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } } -static void -draw_page (GtkPrintOperation *operation, - GtkPrintContext *print_context, - gint page_number, - SimpleScan *ui) -{ - cairo_t *context; - Page *page; - GdkPixbuf *image; - gboolean is_landscape = FALSE; - - context = gtk_print_context_get_cairo_context (print_context); - - page = book_get_page (ui->priv->book, page_number); - - /* Rotate to same aspect */ - if (gtk_print_context_get_width (print_context) > gtk_print_context_get_height (print_context)) - is_landscape = TRUE; - if (page_is_landscape (page) != is_landscape) { - cairo_translate (context, gtk_print_context_get_width (print_context), 0); - cairo_rotate (context, M_PI_2); - } - - cairo_scale (context, - gtk_print_context_get_dpi_x (print_context) / page_get_dpi (page), - gtk_print_context_get_dpi_y (print_context) / page_get_dpi (page)); - - image = page_get_image (page, TRUE); - gdk_cairo_set_source_pixbuf (context, image, 0, 0); - cairo_paint (context); - - g_object_unref (image); -} - - -void email_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -email_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - g_signal_emit (G_OBJECT (ui), signals[EMAIL], 0, ui->priv->document_hint); -} - - -void print_button_clicked_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -print_button_clicked_cb (GtkWidget *widget, SimpleScan *ui) -{ - GtkPrintOperation *print; - GtkPrintOperationResult result; - GError *error = NULL; - - print = gtk_print_operation_new (); - gtk_print_operation_set_n_pages (print, book_get_n_pages (ui->priv->book)); - g_signal_connect (print, "draw-page", G_CALLBACK (draw_page), ui); - - result = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, - GTK_WINDOW (ui->priv->window), &error); - - g_object_unref (print); -} - - -void help_contents_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -help_contents_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - GdkScreen *screen; - GError *error = NULL; - - screen = gtk_widget_get_screen (GTK_WIDGET (ui->priv->window)); - gtk_show_uri (screen, "ghelp:simple-scan", gtk_get_current_event_time (), &error); - - if (error) - { - show_error_dialog (ui, - /* Error message displayed when unable to launch help browser */ - _("Unable to open help file"), - error->message); - g_clear_error (&error); - } -} - - -void about_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -about_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - const gchar *authors[] = { "Robert Ancell <robert.ancell@canonical.com>", NULL }; - - /* The license this software is under (GPL3+) */ - const char *license = _("This program is free software: you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation, either version 3 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program. If not, see <http://www.gnu.org/licenses/>."); - - /* Title of about dialog */ - const char *title = _("About Simple Scan"); - - /* Description of program */ - const char *description = _("Simple document scanning tool"); - - gtk_show_about_dialog (GTK_WINDOW (ui->priv->window), - "title", title, - "program-name", "Simple Scan", - "version", VERSION, - "comments", description, - "logo-icon-name", "scanner", - "authors", authors, - "translator-credits", _("translator-credits"), - "website", "https://launchpad.net/simple-scan", - "copyright", "Copyright © 2009 Canonical Ltd.", - "license", license, - "wrap-license", TRUE, - NULL); -} - - -static gboolean -quit (SimpleScan *ui) -{ - char *device; - gint paper_width = 0, paper_height = 0; - gint i; - - if (!prompt_to_save (ui, - /* Text in dialog warning when a document is about to be lost */ - _("Save document before quitting?"), - /* Button in dialog to quit and discard unsaved document */ - _("Quit without Saving"))) - return FALSE; - - device = get_selected_device (ui); - if (device) { - gconf_client_set_string(ui->priv->client, GCONF_DIR "/selected_device", device, NULL); - g_free (device); - } - - gconf_client_set_string (ui->priv->client, GCONF_DIR "/document_type", ui->priv->document_hint, NULL); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/text_dpi", get_text_dpi (ui), NULL); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/photo_dpi", get_photo_dpi (ui), NULL); - gconf_client_set_string (ui->priv->client, GCONF_DIR "/page_side", get_page_side (ui), NULL); - get_paper_size (ui, &paper_width, &paper_height); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/paper_width", paper_width, NULL); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/paper_height", paper_height, NULL); - - gconf_client_set_int(ui->priv->client, GCONF_DIR "/window_width", ui->priv->window_width, NULL); - gconf_client_set_int(ui->priv->client, GCONF_DIR "/window_height", ui->priv->window_height, NULL); - gconf_client_set_bool(ui->priv->client, GCONF_DIR "/window_is_maximized", ui->priv->window_is_maximized, NULL); - - for (i = 0; scan_direction_keys[i].key != NULL && scan_direction_keys[i].scan_direction != ui->priv->default_page_scan_direction; i++); - if (scan_direction_keys[i].key != NULL) - gconf_client_set_string(ui->priv->client, GCONF_DIR "/scan_direction", scan_direction_keys[i].key, NULL); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/page_width", ui->priv->default_page_width, NULL); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/page_height", ui->priv->default_page_height, NULL); - gconf_client_set_int (ui->priv->client, GCONF_DIR "/page_dpi", ui->priv->default_page_dpi, NULL); - - g_signal_emit (G_OBJECT (ui), signals[QUIT], 0); - - return TRUE; -} - - -void quit_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui); -G_MODULE_EXPORT -void -quit_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui) -{ - quit (ui); -} - - -gboolean simple_scan_window_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, SimpleScan *ui); -G_MODULE_EXPORT -gboolean -simple_scan_window_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, SimpleScan *ui) -{ - if (!ui->priv->window_is_maximized) { - ui->priv->window_width = event->width; - ui->priv->window_height = event->height; - } - - return FALSE; -} - - -static void -info_bar_response_cb (GtkWidget *widget, gint response_id, SimpleScan *ui) -{ - if (response_id == 1) { - gtk_widget_grab_focus (ui->priv->device_combo); - gtk_window_present (GTK_WINDOW (ui->priv->preferences_dialog)); - } - else { - ui->priv->have_error = FALSE; - g_free (ui->priv->error_title); - ui->priv->error_title = NULL; - g_free (ui->priv->error_text); - ui->priv->error_text = NULL; - update_info_bar (ui); - } -} - - -gboolean simple_scan_window_window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event, SimpleScan *ui); -G_MODULE_EXPORT -gboolean -simple_scan_window_window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event, SimpleScan *ui) -{ - if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) - ui->priv->window_is_maximized = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0; - return FALSE; -} - - -gboolean window_delete_event_cb (GtkWidget *widget, GdkEvent *event, SimpleScan *ui); -G_MODULE_EXPORT -gboolean -window_delete_event_cb (GtkWidget *widget, GdkEvent *event, SimpleScan *ui) -{ - return !quit (ui); -} - - -static void -page_size_changed_cb (Page *page, SimpleScan *ui) -{ - ui->priv->default_page_width = page_get_width (page); - ui->priv->default_page_height = page_get_height (page); - ui->priv->default_page_dpi = page_get_dpi (page); +static gpointer value_simple_scan_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; } -static void -page_scan_direction_changed_cb (Page *page, SimpleScan *ui) -{ - ui->priv->default_page_scan_direction = page_get_scan_direction (page); +static gchar* value_simple_scan_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + SimpleScan* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = simple_scan_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; } -static void -page_added_cb (Book *book, Page *page, SimpleScan *ui) -{ - ui->priv->default_page_width = page_get_width (page); - ui->priv->default_page_height = page_get_height (page); - ui->priv->default_page_dpi = page_get_dpi (page); - ui->priv->default_page_scan_direction = page_get_scan_direction (page); - g_signal_connect (page, "size-changed", G_CALLBACK (page_size_changed_cb), ui); - g_signal_connect (page, "scan-direction-changed", G_CALLBACK (page_scan_direction_changed_cb), ui); - - update_page_menu (ui); +static gchar* value_simple_scan_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + SimpleScan** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = simple_scan_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_simple_scan (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecSimpleScan* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_SIMPLE_SCAN), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_simple_scan (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SIMPLE_SCAN), NULL); + return value->data[0].v_pointer; +} + + +void value_set_simple_scan (GValue* value, gpointer v_object) { + SimpleScan* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SIMPLE_SCAN)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SIMPLE_SCAN)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + simple_scan_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + simple_scan_unref (old); + } +} + + +void value_take_simple_scan (GValue* value, gpointer v_object) { + SimpleScan* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SIMPLE_SCAN)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SIMPLE_SCAN)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + simple_scan_unref (old); + } +} + + +static void simple_scan_class_init (SimpleScanClass * klass) { + simple_scan_parent_class = g_type_class_peek_parent (klass); + SIMPLE_SCAN_CLASS (klass)->finalize = simple_scan_finalize; + g_type_class_add_private (klass, sizeof (SimpleScanPrivate)); + g_signal_new ("start_scan", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__STRING_SCAN_OPTIONS, G_TYPE_NONE, 2, G_TYPE_STRING, TYPE_SCAN_OPTIONS); + g_signal_new ("stop_scan", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("email", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + g_signal_new ("quit", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +} + + +static void simple_scan_instance_init (SimpleScan * self) { + gchar* _tmp0_; + const gchar* _tmp1_ = NULL; + gchar* _tmp2_; + self->priv = SIMPLE_SCAN_GET_PRIVATE (self); + self->priv->book_uri = NULL; + _tmp0_ = g_strdup ("photo"); + self->priv->document_hint = _tmp0_; + _tmp1_ = _ ("Scanned Document.pdf"); + _tmp2_ = g_strdup (_tmp1_); + self->priv->default_file_name = _tmp2_; + self->priv->scanning = FALSE; + self->ref_count = 1; +} + + +static void simple_scan_finalize (SimpleScan* obj) { + SimpleScan * self; + self = SIMPLE_SCAN (obj); + _g_object_unref0 (self->priv->settings); + _g_object_unref0 (self->priv->builder); + _g_object_unref0 (self->priv->window); + _g_object_unref0 (self->priv->main_vbox); + _g_object_unref0 (self->priv->info_bar); + _g_object_unref0 (self->priv->info_bar_image); + _g_object_unref0 (self->priv->info_bar_label); + _g_object_unref0 (self->priv->info_bar_close_button); + _g_object_unref0 (self->priv->info_bar_change_scanner_button); + _g_object_unref0 (self->priv->page_move_left_menuitem); + _g_object_unref0 (self->priv->page_move_right_menuitem); + _g_object_unref0 (self->priv->page_delete_menuitem); + _g_object_unref0 (self->priv->crop_rotate_menuitem); + _g_object_unref0 (self->priv->save_menuitem); + _g_object_unref0 (self->priv->save_as_menuitem); + _g_object_unref0 (self->priv->save_toolbutton); + _g_object_unref0 (self->priv->stop_menuitem); + _g_object_unref0 (self->priv->stop_toolbutton); + _g_object_unref0 (self->priv->text_toolbar_menuitem); + _g_object_unref0 (self->priv->text_menu_menuitem); + _g_object_unref0 (self->priv->photo_toolbar_menuitem); + _g_object_unref0 (self->priv->photo_menu_menuitem); + _g_object_unref0 (self->priv->authorize_dialog); + _g_object_unref0 (self->priv->authorize_label); + _g_object_unref0 (self->priv->username_entry); + _g_object_unref0 (self->priv->password_entry); + _g_object_unref0 (self->priv->preferences_dialog); + _g_object_unref0 (self->priv->device_combo); + _g_object_unref0 (self->priv->text_dpi_combo); + _g_object_unref0 (self->priv->photo_dpi_combo); + _g_object_unref0 (self->priv->page_side_combo); + _g_object_unref0 (self->priv->paper_size_combo); + _g_object_unref0 (self->priv->device_model); + _g_object_unref0 (self->priv->text_dpi_model); + _g_object_unref0 (self->priv->photo_dpi_model); + _g_object_unref0 (self->priv->page_side_model); + _g_object_unref0 (self->priv->paper_size_model); + _g_object_unref0 (self->priv->save_dialog); + _g_free0 (self->priv->error_title); + _g_free0 (self->priv->error_text); + _book_unref0 (self->priv->book); + _g_free0 (self->priv->book_uri); + _g_object_unref0 (self->priv->book_view); + _g_free0 (self->priv->document_hint); + _g_free0 (self->priv->default_file_name); +} + + +GType simple_scan_get_type (void) { + static volatile gsize simple_scan_type_id__volatile = 0; + if (g_once_init_enter (&simple_scan_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_simple_scan_init, value_simple_scan_free_value, value_simple_scan_copy_value, value_simple_scan_peek_pointer, "p", value_simple_scan_collect_value, "p", value_simple_scan_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (SimpleScanClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) simple_scan_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SimpleScan), 0, (GInstanceInitFunc) simple_scan_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType simple_scan_type_id; + simple_scan_type_id = g_type_register_fundamental (g_type_fundamental_next (), "SimpleScan", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&simple_scan_type_id__volatile, simple_scan_type_id); + } + return simple_scan_type_id__volatile; +} + + +gpointer simple_scan_ref (gpointer instance) { + SimpleScan* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void simple_scan_unref (gpointer instance) { + SimpleScan* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + SIMPLE_SCAN_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); } -static void -page_removed_cb (Book *book, Page *page, SimpleScan *ui) -{ - /* If this is the last page add a new blank one */ - if (book_get_n_pages (ui->priv->book) == 1) - add_default_page (ui); - update_page_menu (ui); -} - - -static void -set_dpi_combo (GtkWidget *combo, gint default_dpi, gint current_dpi) -{ - struct - { - gint dpi; - const gchar *label; - } scan_resolutions[] = - { - /* Preferences dialog: Label for minimum resolution in resolution list */ - { 75, _("%d dpi (draft)") }, - /* Preferences dialog: Label for resolution value in resolution list (dpi = dots per inch) */ - { 150, _("%d dpi") }, - { 300, _("%d dpi") }, - { 600, _("%d dpi") }, - /* Preferences dialog: Label for maximum resolution in resolution list */ - { 1200, _("%d dpi (high resolution)") }, - { 2400, _("%d dpi") }, - { -1, NULL } - }; - GtkCellRenderer *renderer; - GtkTreeModel *model; - gint i; - - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 1); - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); - for (i = 0; scan_resolutions[i].dpi > 0; i++) - { - GtkTreeIter iter; - gchar *label; - gint dpi; - - dpi = scan_resolutions[i].dpi; - - if (dpi == default_dpi) - label = g_strdup_printf (/* Preferences dialog: Label for default resolution in resolution list */ - _("%d dpi (default)"), dpi); - else - label = g_strdup_printf (scan_resolutions[i].label, dpi); - - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, dpi, 1, label, -1); - - if (dpi == current_dpi) - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter); - - g_free (label); - } -} - - -static void -needs_saving_cb (Book *book, GParamSpec *param, SimpleScan *ui) -{ - gtk_widget_set_sensitive (ui->priv->save_menuitem, book_get_needs_saving (book)); - gtk_widget_set_sensitive (ui->priv->save_toolbutton, book_get_needs_saving (book)); - if (book_get_needs_saving (book)) - gtk_widget_set_sensitive (ui->priv->save_as_menuitem, TRUE); -} - - -static void -ui_load (SimpleScan *ui) -{ - GtkBuilder *builder; - GError *error = NULL; - GtkWidget *hbox; - GtkCellRenderer *renderer; - gchar *device, *document_type, *scan_direction, *page_side; - gint dpi, paper_width, paper_height; - - gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), ICON_DIR); - - gtk_window_set_default_icon_name ("scanner"); - - builder = ui->priv->builder = gtk_builder_new (); - gtk_builder_add_from_file (builder, UI_DIR "simple-scan.ui", &error); - if (error) { - g_critical ("Unable to load UI: %s\n", error->message); - show_error_dialog (ui, - /* Title of dialog when cannot load required files */ - _("Files missing"), - /* Description in dialog when cannot load required files */ - _("Please check your installation")); - exit (1); - } - gtk_builder_connect_signals (builder, ui); - - ui->priv->window = GTK_WIDGET (gtk_builder_get_object (builder, "simple_scan_window")); - ui->priv->main_vbox = GTK_WIDGET (gtk_builder_get_object (builder, "main_vbox")); - ui->priv->page_move_left_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "page_move_left_menuitem")); - ui->priv->page_move_right_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "page_move_right_menuitem")); - ui->priv->page_delete_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "page_delete_menuitem")); - ui->priv->crop_rotate_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "crop_rotate_menuitem")); - ui->priv->save_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "save_menuitem")); - ui->priv->save_as_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "save_as_menuitem")); - ui->priv->save_toolbutton = GTK_WIDGET (gtk_builder_get_object (builder, "save_toolbutton")); - ui->priv->stop_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "stop_scan_menuitem")); - ui->priv->stop_toolbutton = GTK_WIDGET (gtk_builder_get_object (builder, "stop_toolbutton")); - - ui->priv->text_toolbar_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "text_toolbutton_menuitem")); - ui->priv->text_menu_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "text_menuitem")); - ui->priv->photo_toolbar_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "photo_toolbutton_menuitem")); - ui->priv->photo_menu_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "photo_menuitem")); - - ui->priv->authorize_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "authorize_dialog")); - ui->priv->authorize_label = GTK_WIDGET (gtk_builder_get_object (builder, "authorize_label")); - ui->priv->username_entry = GTK_WIDGET (gtk_builder_get_object (builder, "username_entry")); - ui->priv->password_entry = GTK_WIDGET (gtk_builder_get_object (builder, "password_entry")); - - ui->priv->preferences_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "preferences_dialog")); - ui->priv->device_combo = GTK_WIDGET (gtk_builder_get_object (builder, "device_combo")); - ui->priv->device_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->device_combo)); - ui->priv->text_dpi_combo = GTK_WIDGET (gtk_builder_get_object (builder, "text_dpi_combo")); - ui->priv->text_dpi_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->text_dpi_combo)); - ui->priv->photo_dpi_combo = GTK_WIDGET (gtk_builder_get_object (builder, "photo_dpi_combo")); - ui->priv->photo_dpi_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->photo_dpi_combo)); - ui->priv->page_side_combo = GTK_WIDGET (gtk_builder_get_object (builder, "page_side_combo")); - ui->priv->page_side_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->page_side_combo)); - ui->priv->paper_size_combo = GTK_WIDGET (gtk_builder_get_object (builder, "paper_size_combo")); - ui->priv->paper_size_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->paper_size_combo)); - - /* Add InfoBar (not supported in Glade) */ - ui->priv->info_bar = gtk_info_bar_new (); - g_signal_connect (ui->priv->info_bar, "response", G_CALLBACK (info_bar_response_cb), ui); - gtk_box_pack_start (GTK_BOX(ui->priv->main_vbox), ui->priv->info_bar, FALSE, TRUE, 0); - hbox = gtk_hbox_new (FALSE, 12); - gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (ui->priv->info_bar))), hbox); - gtk_widget_show (hbox); - - ui->priv->info_bar_image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX(hbox), ui->priv->info_bar_image, FALSE, TRUE, 0); - gtk_widget_show (ui->priv->info_bar_image); - - ui->priv->info_bar_label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (ui->priv->info_bar_label), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX(hbox), ui->priv->info_bar_label, TRUE, TRUE, 0); - gtk_widget_show (ui->priv->info_bar_label); - - ui->priv->info_bar_close_button = gtk_info_bar_add_button (GTK_INFO_BAR (ui->priv->info_bar), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); - ui->priv->info_bar_change_scanner_button = gtk_info_bar_add_button (GTK_INFO_BAR (ui->priv->info_bar), - /* Button in error infobar to open preferences dialog and change scanner */ - _("Change _Scanner"), 1); - - GtkTreeIter iter; - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 0, 1, 0, 2, - /* Combo box value for automatic paper size */ - _("Automatic"), -1); - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 1050, 1, 1480, 2, "A6", -1); - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 1480, 1, 2100, 2, "A5", -1); - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 2100, 1, 2970, 2, "A4", -1); - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 2159, 1, 2794, 2, "Letter", -1); - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 2159, 1, 3556, 2, "Legal", -1); - gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 1016, 1, 1524, 2, "4×6", -1); - - dpi = gconf_client_get_int (ui->priv->client, GCONF_DIR "/text_dpi", NULL); - if (dpi <= 0) - dpi = DEFAULT_TEXT_DPI; - set_dpi_combo (ui->priv->text_dpi_combo, DEFAULT_TEXT_DPI, dpi); - dpi = gconf_client_get_int (ui->priv->client, GCONF_DIR "/photo_dpi", NULL); - if (dpi <= 0) - dpi = DEFAULT_PHOTO_DPI; - set_dpi_combo (ui->priv->photo_dpi_combo, DEFAULT_PHOTO_DPI, dpi); - - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->priv->device_combo), renderer, TRUE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ui->priv->device_combo), renderer, "text", 1); - - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->priv->page_side_combo), renderer, TRUE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ui->priv->page_side_combo), renderer, "text", 1); - page_side = gconf_client_get_string (ui->priv->client, GCONF_DIR "/page_side", NULL); - if (page_side) { - set_page_side (ui, page_side); - g_free (page_side); - } - - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->priv->paper_size_combo), renderer, TRUE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ui->priv->paper_size_combo), renderer, "text", 2); - paper_width = gconf_client_get_int (ui->priv->client, GCONF_DIR "/paper_width", NULL); - paper_height = gconf_client_get_int (ui->priv->client, GCONF_DIR "/paper_height", NULL); - set_paper_size (ui, paper_width, paper_height); - - device = gconf_client_get_string (ui->priv->client, GCONF_DIR "/selected_device", NULL); - if (device) { - GtkTreeIter iter; - if (find_scan_device (ui, device, &iter)) - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->device_combo), &iter); - g_free (device); - } - - document_type = gconf_client_get_string (ui->priv->client, GCONF_DIR "/document_type", NULL); - if (document_type) { - set_document_hint (ui, document_type); - g_free (document_type); - } - - ui->priv->book_view = book_view_new (ui->priv->book); - gtk_container_set_border_width (GTK_CONTAINER (ui->priv->book_view), 18); - gtk_box_pack_end (GTK_BOX (ui->priv->main_vbox), GTK_WIDGET (ui->priv->book_view), TRUE, TRUE, 0); - g_signal_connect (ui->priv->book_view, "page-selected", G_CALLBACK (page_selected_cb), ui); - g_signal_connect (ui->priv->book_view, "show-page", G_CALLBACK (show_page_cb), ui); - g_signal_connect (ui->priv->book_view, "show-menu", G_CALLBACK (show_page_menu_cb), ui); - gtk_widget_show (GTK_WIDGET (ui->priv->book_view)); - - /* Find default page details */ - scan_direction = gconf_client_get_string(ui->priv->client, GCONF_DIR "/scan_direction", NULL); - ui->priv->default_page_scan_direction = TOP_TO_BOTTOM; - if (scan_direction) { - gint i; - for (i = 0; scan_direction_keys[i].key != NULL && strcmp (scan_direction_keys[i].key, scan_direction) != 0; i++); - if (scan_direction_keys[i].key != NULL) - ui->priv->default_page_scan_direction = scan_direction_keys[i].scan_direction; - g_free (scan_direction); - } - ui->priv->default_page_width = gconf_client_get_int (ui->priv->client, GCONF_DIR "/page_width", NULL); - if (ui->priv->default_page_width <= 0) - ui->priv->default_page_width = 595; - ui->priv->default_page_height = gconf_client_get_int (ui->priv->client, GCONF_DIR "/page_height", NULL); - if (ui->priv->default_page_height <= 0) - ui->priv->default_page_height = 842; - ui->priv->default_page_dpi = gconf_client_get_int (ui->priv->client, GCONF_DIR "/page_dpi", NULL); - if (ui->priv->default_page_dpi <= 0) - ui->priv->default_page_dpi = 72; - - /* Restore window size */ - ui->priv->window_width = gconf_client_get_int (ui->priv->client, GCONF_DIR "/window_width", NULL); - if (ui->priv->window_width <= 0) - ui->priv->window_width = 600; - ui->priv->window_height = gconf_client_get_int (ui->priv->client, GCONF_DIR "/window_height", NULL); - if (ui->priv->window_height <= 0) - ui->priv->window_height = 400; - g_debug ("Restoring window to %dx%d pixels", ui->priv->window_width, ui->priv->window_height); - gtk_window_set_default_size (GTK_WINDOW (ui->priv->window), ui->priv->window_width, ui->priv->window_height); - ui->priv->window_is_maximized = gconf_client_get_bool (ui->priv->client, GCONF_DIR "/window_is_maximized", NULL); - if (ui->priv->window_is_maximized) { - g_debug ("Restoring window to maximized"); - gtk_window_maximize (GTK_WINDOW (ui->priv->window)); - } - - if (book_get_n_pages (ui->priv->book) == 0) - add_default_page (ui); - book_set_needs_saving (ui->priv->book, FALSE); - g_signal_connect (ui->priv->book, "notify::needs-saving", G_CALLBACK (needs_saving_cb), ui); -} - - -SimpleScan * -ui_new () -{ - return g_object_new (SIMPLE_SCAN_TYPE, NULL); -} - - -Book * -ui_get_book (SimpleScan *ui) -{ - return g_object_ref (ui->priv->book); -} - - -void -ui_set_selected_page (SimpleScan *ui, Page *page) -{ - book_view_select_page (ui->priv->book_view, page); -} - - -Page * -ui_get_selected_page (SimpleScan *ui) -{ - return book_view_get_selected (ui->priv->book_view); -} - - -void -ui_set_scanning (SimpleScan *ui, gboolean scanning) -{ - ui->priv->scanning = scanning; - gtk_widget_set_sensitive (ui->priv->page_delete_menuitem, !scanning); - gtk_widget_set_sensitive (ui->priv->stop_menuitem, scanning); - gtk_widget_set_sensitive (ui->priv->stop_toolbutton, scanning); -} - - -void -ui_show_error (SimpleScan *ui, const gchar *error_title, const gchar *error_text, gboolean change_scanner_hint) -{ - ui->priv->have_error = TRUE; - g_free (ui->priv->error_title); - ui->priv->error_title = g_strdup (error_title); - g_free (ui->priv->error_text); - ui->priv->error_text = g_strdup (error_text); - ui->priv->error_change_scanner_hint = change_scanner_hint; - update_info_bar (ui); -} - - -void -ui_start (SimpleScan *ui) -{ - gtk_widget_show (ui->priv->window); -} - - -/* Generated with glib-genmarshal */ -static void -g_cclosure_user_marshal_VOID__STRING_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1, - gconstpointer arg_1, - gconstpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__STRING_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_value_get_string (param_values + 1), - g_value_get_pointer (param_values + 2), - data2); -} - - -static void -ui_finalize (GObject *object) -{ - SimpleScan *ui = SIMPLE_SCAN (object); - - g_object_unref (ui->priv->client); - ui->priv->client = NULL; - g_object_unref (ui->priv->builder); - ui->priv->builder = NULL; - g_object_unref (ui->priv->book); - ui->priv->book = NULL; - gtk_widget_destroy (GTK_WIDGET (ui->priv->book_view)); - ui->priv->book_view = NULL; - - G_OBJECT_CLASS (ui_parent_class)->finalize (object); -} - - -static void -ui_class_init (SimpleScanClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = ui_finalize; - - signals[START_SCAN] = - g_signal_new ("start-scan", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SimpleScanClass, start_scan), - NULL, NULL, - g_cclosure_user_marshal_VOID__STRING_POINTER, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER); - signals[STOP_SCAN] = - g_signal_new ("stop-scan", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SimpleScanClass, stop_scan), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[EMAIL] = - g_signal_new ("email", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SimpleScanClass, email), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - signals[QUIT] = - g_signal_new ("quit", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SimpleScanClass, quit), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (SimpleScanPrivate)); -} - - -static void -ui_init (SimpleScan *ui) -{ - ui->priv = G_TYPE_INSTANCE_GET_PRIVATE (ui, SIMPLE_SCAN_TYPE, SimpleScanPrivate); - - ui->priv->book = book_new (); - g_signal_connect (ui->priv->book, "page-removed", G_CALLBACK (page_removed_cb), ui); - g_signal_connect (ui->priv->book, "page-added", G_CALLBACK (page_added_cb), ui); - - ui->priv->client = gconf_client_get_default(); - gconf_client_add_dir(ui->priv->client, GCONF_DIR, GCONF_CLIENT_PRELOAD_NONE, NULL); - - ui->priv->document_hint = g_strdup ("photo"); - ui->priv->default_file_name = g_strdup (_("Scanned Document.pdf")); - ui->priv->scanning = FALSE; - ui_load (ui); -} diff --git a/src/ui.h b/src/ui.h deleted file mode 100644 index d43c187..0000000 --- a/src/ui.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2009 Canonical Ltd. - * Author: Robert Ancell <robert.ancell@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. See http://www.gnu.org/copyleft/gpl.html the full text of the - * license. - */ - -#ifndef _UI_H_ -#define _UI_H_ - -#include <glib-object.h> -#include "book.h" -#include "scanner.h" - -G_BEGIN_DECLS - -#define SIMPLE_SCAN_TYPE (ui_get_type ()) -#define SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SIMPLE_SCAN_TYPE, SimpleScan)) - - -typedef struct SimpleScanPrivate SimpleScanPrivate; - -typedef struct -{ - GObject parent_instance; - SimpleScanPrivate *priv; -} SimpleScan; - -typedef struct -{ - GObjectClass parent_class; - - void (*start_scan) (SimpleScan *ui, ScanOptions *options); - void (*stop_scan) (SimpleScan *ui); - void (*email) (SimpleScan *ui, const gchar *profile); - void (*quit) (SimpleScan *ui); -} SimpleScanClass; - - -GType ui_get_type (void); - -SimpleScan *ui_new (void); - -Book *ui_get_book (SimpleScan *ui); - -void ui_set_selected_page (SimpleScan *ui, Page *page); - -Page *ui_get_selected_page (SimpleScan *ui); - -void ui_set_default_file_name (SimpleScan *ui, const gchar *default_file_name); - -void ui_authorize (SimpleScan *ui, const gchar *resource, gchar **username, gchar **password); - -void ui_set_scan_devices (SimpleScan *ui, GList *devices); - -gchar *ui_get_selected_device (SimpleScan *ui); - -void ui_set_selected_device (SimpleScan *ui, const gchar *device); - -void ui_set_scanning (SimpleScan *ui, gboolean scanning); - -void ui_show_error (SimpleScan *ui, const gchar *error_title, const gchar *error_text, gboolean change_scanner_hint); - -void ui_start (SimpleScan *ui); - -#endif /* _UI_H_ */ diff --git a/src/ui.vala b/src/ui.vala new file mode 100644 index 0000000..4287d13 --- /dev/null +++ b/src/ui.vala @@ -0,0 +1,1458 @@ +/* + * Copyright (C) 2009-2011 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public class SimpleScan +{ + private const int DEFAULT_TEXT_DPI = 150; + private const int DEFAULT_PHOTO_DPI = 300; + + private Settings settings; + + private Gtk.Builder builder; + + private Gtk.Window window; + private Gtk.VBox main_vbox; + private Gtk.InfoBar info_bar; + private Gtk.Image info_bar_image; + private Gtk.Label info_bar_label; + private Gtk.Button info_bar_close_button; + private Gtk.Button info_bar_change_scanner_button; + private Gtk.MenuItem page_move_left_menuitem; + private Gtk.MenuItem page_move_right_menuitem; + private Gtk.MenuItem page_delete_menuitem; + private Gtk.MenuItem crop_rotate_menuitem; + private Gtk.MenuItem save_menuitem; + private Gtk.MenuItem save_as_menuitem; + private Gtk.ToolButton save_toolbutton; + private Gtk.MenuItem stop_menuitem; + private Gtk.ToolButton stop_toolbutton; + + private Gtk.RadioMenuItem text_toolbar_menuitem; + private Gtk.RadioMenuItem text_menu_menuitem; + private Gtk.RadioMenuItem photo_toolbar_menuitem; + private Gtk.RadioMenuItem photo_menu_menuitem; + + private Gtk.Dialog authorize_dialog; + private Gtk.Label authorize_label; + private Gtk.Entry username_entry; + private Gtk.Entry password_entry; + + private Gtk.Dialog preferences_dialog; + private Gtk.ComboBox device_combo; + private Gtk.ComboBox text_dpi_combo; + private Gtk.ComboBox photo_dpi_combo; + private Gtk.ComboBox page_side_combo; + private Gtk.ComboBox paper_size_combo; + private Gtk.ListStore device_model; + private Gtk.ListStore text_dpi_model; + private Gtk.ListStore photo_dpi_model; + private Gtk.ListStore page_side_model; + private Gtk.ListStore paper_size_model; + private bool setting_devices; + private bool user_selected_device; + + private Gtk.FileChooserDialog? save_dialog; + + private bool have_error; + private string error_title; + private string error_text; + private bool error_change_scanner_hint; + + private Book book; + private string? book_uri = null; + + private BookView book_view; + private bool updating_page_menu; + private int default_page_width; + private int default_page_height; + private int default_page_dpi; + private ScanDirection default_page_scan_direction; + + private string document_hint = "photo"; + + private string default_file_name = _("Scanned Document.pdf"); + private bool scanning = false; + + private int window_width; + private int window_height; + private bool window_is_maximized; + + public signal void start_scan (string? device, ScanOptions options); + public signal void stop_scan (); + public signal void email (string profile); + public signal void quit (); + + public SimpleScan () + { + book = new Book (); + book.page_removed.connect (page_removed_cb); + book.page_added.connect (page_added_cb); + + settings = new Settings ("org.gnome.SimpleScan"); + + load (); + } + + private bool find_scan_device (string device, out Gtk.TreeIter iter) + { + bool have_iter = false; + + if (device_model.get_iter_first (out iter)) + { + do + { + string d; + device_model.get (iter, 0, out d, -1); + if (d == device) + have_iter = true; + } while (!have_iter && device_model.iter_next (ref iter)); + } + + return have_iter; + } + + private void show_error_dialog (string error_title, string error_text) + { + var dialog = new Gtk.MessageDialog (window, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.WARNING, + Gtk.ButtonsType.NONE, + "%s", error_title); + dialog.add_button (Gtk.Stock.CLOSE, 0); + dialog.format_secondary_text ("%s", error_text); + dialog.destroy (); + } + + public void set_default_file_name (string default_file_name) + { + this.default_file_name = default_file_name; + } + + public void authorize (string resource, out string username, out string password) + { + /* Label in authorization dialog. '%s' is replaced with the name of the resource requesting authorization */ + var description = _("Username and password required to access '%s'").printf (resource); + + username_entry.set_text (""); + password_entry.set_text (""); + authorize_label.set_text (description); + + authorize_dialog.show (); + authorize_dialog.run (); + authorize_dialog.hide (); + + username = username_entry.get_text (); + password = password_entry.get_text (); + } + + [CCode (cname = "G_MODULE_EXPORT device_combo_changed_cb", instance_pos = -1)] + public void device_combo_changed_cb (Gtk.Widget widget) + { + if (setting_devices) + return; + user_selected_device = true; + } + + private void update_info_bar () + { + Gtk.MessageType type; + string title, text, image_id; + bool show_close_button = false; + bool show_change_scanner_button = false; + + if (have_error) + { + type = Gtk.MessageType.ERROR; + image_id = Gtk.Stock.DIALOG_ERROR; + title = error_title; + text = error_text; + show_close_button = true; + show_change_scanner_button = error_change_scanner_hint; + } + else if (device_model.iter_n_children (null) == 0) + { + type = Gtk.MessageType.WARNING; + image_id = Gtk.Stock.DIALOG_WARNING; + /* Warning displayed when no scanners are detected */ + title = _("No scanners detected"); + /* Hint to user on why there are no scanners detected */ + text = _("Please check your scanner is connected and powered on"); + } + else + { + info_bar.hide (); + return; + } + + info_bar.set_message_type (type); + info_bar_image.set_from_stock (image_id, Gtk.IconSize.DIALOG); + var message = "<big><b>%s</b></big>\n\n%s".printf (title, text); + info_bar_label.set_markup (message); + info_bar_close_button.set_visible (show_close_button); + info_bar_change_scanner_button.set_visible (show_change_scanner_button); + info_bar.show (); + } + + public void set_scan_devices (List<ScanDevice> devices) + { + bool have_selection = false; + int index; + Gtk.TreeIter iter; + + setting_devices = true; + + /* If the user hasn't chosen a scanner choose the best available one */ + if (user_selected_device) + have_selection = device_combo.get_active () >= 0; + + /* Add new devices */ + index = 0; + foreach (var device in devices) + { + int n_delete = -1; + + /* Find if already exists */ + if (device_model.iter_nth_child (out iter, null, index)) + { + int i = 0; + do + { + string name; + bool matched; + + device_model.get (iter, 0, out name, -1); + matched = name == device.name; + + if (matched) + { + n_delete = i; + break; + } + i++; + } while (device_model.iter_next (ref iter)); + } + + /* If exists, remove elements up to this one */ + if (n_delete >= 0) + { + int i; + + /* Update label */ + device_model.set (iter, 1, device.label, -1); + + for (i = 0; i < n_delete; i++) + { + device_model.iter_nth_child (out iter, null, index); + device_model.remove (iter); + } + } + else + { + device_model.insert (out iter, index); + device_model.set (iter, 0, device.name, 1, device.label, -1); + } + index++; + } + + /* Remove any remaining devices */ + while (device_model.iter_nth_child (out iter, null, index)) + device_model.remove (iter); + + /* Select the first available device */ + if (!have_selection && devices != null) + device_combo.set_active (0); + + setting_devices = false; + + update_info_bar (); + } + + private string? get_selected_device () + { + Gtk.TreeIter iter; + + if (device_combo.get_active_iter (out iter)) + { + string device; + device_model.get (iter, 0, out device, -1); + return device; + } + + return null; + } + + public void set_selected_device (string device) + { + Gtk.TreeIter iter; + if (!find_scan_device (device, out iter)) + return; + + device_combo.set_active_iter (iter); + user_selected_device = true; + } + + private void add_default_page () + { + var page = book.append_page (default_page_width, + default_page_height, + default_page_dpi, + default_page_scan_direction); + book_view.select_page (page); + } + + private void on_file_type_changed (Gtk.TreeSelection selection) + { + Gtk.TreeModel model; + Gtk.TreeIter iter; + if (!selection.get_selected (out model, out iter)) + return; + + string extension; + model.get (iter, 1, out extension, -1); + var path = save_dialog.get_filename (); + var filename = Path.get_basename (path); + + /* Replace extension */ + var extension_index = filename.last_index_of_char ('.'); + if (extension_index >= 0) + filename = filename.slice (0, extension_index); + filename = filename + extension; + save_dialog.set_current_name (filename); + } + + private string choose_file_location () + { + /* Get directory to save to */ + string? directory = null; + directory = settings.get_string ("save-directory"); + + if (directory == null || directory == "") + directory = Environment.get_user_special_dir (UserDirectory.DOCUMENTS); + + save_dialog = new Gtk.FileChooserDialog (/* Save dialog: Dialog title */ + _("Save As..."), + window, + Gtk.FileChooserAction.SAVE, + Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, + Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT, + null); + save_dialog.set_do_overwrite_confirmation (true); + save_dialog.set_local_only (false); + save_dialog.set_current_folder (directory); + save_dialog.set_current_name (default_file_name); + + /* Filter to only show images by default */ + var filter = new Gtk.FileFilter (); + filter.set_name (/* Save dialog: Filter name to show only image files */ + _("Image Files")); + filter.add_pixbuf_formats (); + filter.add_mime_type ("application/pdf"); + save_dialog.add_filter (filter); + filter = new Gtk.FileFilter (); + filter.set_name (/* Save dialog: Filter name to show all files */ + _("All Files")); + filter.add_pattern ("*"); + save_dialog.add_filter (filter); + + var expander = new Gtk.Expander.with_mnemonic (/* */ + _("Select File _Type")); + expander.set_spacing (5); + save_dialog.set_extra_widget (expander); + + string extension = ""; + var index = default_file_name.last_index_of_char ('.'); + if (index >= 0) + extension = default_file_name.slice (0, index); + + var file_type_store = new Gtk.ListStore (2, typeof (string), typeof (string)); + Gtk.TreeIter iter; + file_type_store.append (out iter); + file_type_store.set (iter, + /* Save dialog: Label for saving in PDF format */ + 0, _("PDF (multi-page document)"), + 1, ".pdf", + -1); + file_type_store.append (out iter); + file_type_store.set (iter, + /* Save dialog: Label for saving in JPEG format */ + 0, _("JPEG (compressed)"), + 1, ".jpg", + -1); + file_type_store.append (out iter); + file_type_store.set (iter, + /* Save dialog: Label for saving in PNG format */ + 0, _("PNG (lossless)"), + 1, ".png", + -1); + + var file_type_view = new Gtk.TreeView.with_model (file_type_store); + file_type_view.set_headers_visible (false); + file_type_view.set_rules_hint (true); + var column = new Gtk.TreeViewColumn.with_attributes ("", + new Gtk.CellRendererText (), + "text", 0, null); + file_type_view.append_column (column); + expander.add (file_type_view); + + if (file_type_store.get_iter_first (out iter)) + { + do + { + string e; + file_type_store.get (iter, 1, out e, -1); + if (extension == e) + file_type_view.get_selection ().select_iter (iter); + } while (file_type_store.iter_next (ref iter)); + } + file_type_view.get_selection ().changed.connect (on_file_type_changed); + + expander.show_all (); + + var response = save_dialog.run (); + + string? uri = null; + if (response == Gtk.ResponseType.ACCEPT) + uri = save_dialog.get_uri (); + + settings.set_string ("save-directory", save_dialog.get_current_folder ()); + + save_dialog.destroy (); + save_dialog = null; + + return uri; + } + + private bool save_document (bool force_choose_location) + { + string? uri; + if (book_uri != null && !force_choose_location) + uri = book_uri; + else + uri = choose_file_location (); + if (uri == null) + return false; + + var file = File.new_for_uri (uri); + + debug ("Saving to '%s'", uri); + + var uri_lower = uri.down (); + string format = "jpeg"; + if (uri_lower.has_suffix (".pdf")) + format = "pdf"; + else if (uri_lower.has_suffix (".ps")) + format = "ps"; + else if (uri_lower.has_suffix (".png")) + format = "png"; + else if (uri_lower.has_suffix (".tif") || uri_lower.has_suffix (".tiff")) + format = "tiff"; + + try + { + book.save (format, file); + } + catch (Error e) + { + warning ("Error saving file: %s", e.message); + show_error (/* Title of error dialog when save failed */ + _("Failed to save file"), + e.message, + false); + return false; + } + + book_uri = uri; + book.set_needs_saving (false); + return true; + } + + private bool prompt_to_save (string title, string discard_label) + { + if (!book.get_needs_saving ()) + return true; + + var dialog = new Gtk.MessageDialog (window, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.WARNING, + Gtk.ButtonsType.NONE, + "%s", title); + dialog.format_secondary_text ("%s", + /* Text in dialog warning when a document is about to be lost*/ + _("If you don't save, changes will be permanently lost.")); + dialog.add_button (discard_label, Gtk.ResponseType.NO); + dialog.add_button (Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL); + dialog.add_button (Gtk.Stock.SAVE, Gtk.ResponseType.YES); + + var response = dialog.run (); + dialog.destroy (); + + switch (response) + { + case Gtk.ResponseType.YES: + if (save_document (false)) + return true; + else + return false; + case Gtk.ResponseType.CANCEL: + return false; + case Gtk.ResponseType.NO: + default: + return true; + } + } + + private void clear_document () + { + book.clear (); + add_default_page (); + book_uri = null; + book.set_needs_saving (false); + save_as_menuitem.set_sensitive (false); + } + + [CCode (cname = "G_MODULE_EXPORT new_button_clicked_cb", instance_pos = -1)] + public void new_button_clicked_cb (Gtk.Widget widget) + { + if (!prompt_to_save (/* Text in dialog warning when a document is about to be lost */ + _("Save current document?"), + /* Button in dialog to create new document and discard unsaved document */ + _("Discard Changes"))) + return; + + clear_document (); + } + + private void set_document_hint (string document_hint) + { + this.document_hint = document_hint; + + if (document_hint == "text") + { + text_toolbar_menuitem.set_active (true); + text_menu_menuitem.set_active (true); + } + else if (document_hint == "photo") + { + photo_toolbar_menuitem.set_active (true); + photo_menu_menuitem.set_active (true); + } + } + + [CCode (cname = "G_MODULE_EXPORT text_menuitem_toggled_cb", instance_pos = -1)] + public void text_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_document_hint ("text"); + } + + [CCode (cname = "G_MODULE_EXPORT photo_menuitem_toggled_cb", instance_pos = -1)] + public void photo_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_document_hint ("photo"); + } + + private void set_page_side (ScanType page_side) + { + Gtk.TreeIter iter; + + if (page_side_model.get_iter_first (out iter)) + { + do + { + int s; + page_side_model.get (iter, 0, out s, -1); + if (s == page_side) + { + page_side_combo.set_active_iter (iter); + return; + } + } while (page_side_model.iter_next (ref iter)); + } + } + + private void set_paper_size (int width, int height) + { + Gtk.TreeIter iter; + bool have_iter; + + for (have_iter = paper_size_model.get_iter_first (out iter); + have_iter; + have_iter = paper_size_model.iter_next (ref iter)) + { + int w, h; + paper_size_model.get (iter, 0, out w, 1, out h, -1); + if (w == width && h == height) + break; + } + + if (!have_iter) + have_iter = paper_size_model.get_iter_first (out iter); + if (have_iter) + paper_size_combo.set_active_iter (iter); + } + + private int get_text_dpi () + { + Gtk.TreeIter iter; + int dpi = DEFAULT_TEXT_DPI; + + if (text_dpi_combo.get_active_iter (out iter)) + text_dpi_model.get (iter, 0, out dpi, -1); + + return dpi; + } + + private int get_photo_dpi () + { + Gtk.TreeIter iter; + int dpi = DEFAULT_PHOTO_DPI; + + if (photo_dpi_combo.get_active_iter (out iter)) + photo_dpi_model.get (iter, 0, out dpi, -1); + + return dpi; + } + + private ScanType get_page_side () + { + Gtk.TreeIter iter; + int page_side = ScanType.ADF_BOTH; + + if (page_side_combo.get_active_iter (out iter)) + page_side_model.get (iter, 0, out page_side, -1); + + return (ScanType) page_side; + } + + private bool get_paper_size (out int width, out int height) + { + Gtk.TreeIter iter; + + if (paper_size_combo.get_active_iter (out iter)) + { + paper_size_model.get (iter, 0, ref width, 1, ref height, -1); + return true; + } + + return false; + } + + private ScanOptions get_scan_options () + { + var options = new ScanOptions (); + if (document_hint == "text") + { + options.scan_mode = ScanMode.GRAY; + options.dpi = get_text_dpi (); + options.depth = 2; + } + else + { + options.scan_mode = ScanMode.COLOR; + options.dpi = get_photo_dpi (); + options.depth = 8; + } + get_paper_size (out options.paper_width, out options.paper_height); + + return options; + } + + [CCode (cname = "G_MODULE_EXPORT scan_button_clicked_cb", instance_pos = -1)] + public void scan_button_clicked_cb (Gtk.Widget widget) + { + var options = get_scan_options (); + options.type = ScanType.SINGLE; + start_scan (get_selected_device (), options); + } + + [CCode (cname = "G_MODULE_EXPORT stop_scan_button_clicked_cb", instance_pos = -1)] + public void stop_scan_button_clicked_cb (Gtk.Widget widget) + { + stop_scan (); + } + + [CCode (cname = "G_MODULE_EXPORT continuous_scan_button_clicked_cb", instance_pos = -1)] + public void continuous_scan_button_clicked_cb (Gtk.Widget widget) + { + if (scanning) + stop_scan (); + else + { + var options = get_scan_options (); + options.type = get_page_side (); + start_scan (get_selected_device (), options); + } + } + + [CCode (cname = "G_MODULE_EXPORT preferences_button_clicked_cb", instance_pos = -1)] + public void preferences_button_clicked_cb (Gtk.Widget widget) + { + preferences_dialog.present (); + } + + [CCode (cname = "G_MODULE_EXPORT preferences_dialog_delete_event_cb", instance_pos = -1)] + public bool preferences_dialog_delete_event_cb (Gtk.Widget widget) + { + return true; + } + + [CCode (cname = "G_MODULE_EXPORT preferences_dialog_response_cb", instance_pos = -1)] + public void preferences_dialog_response_cb (Gtk.Widget widget, int response_id) + { + preferences_dialog.hide (); + } + + private void update_page_menu () + { + var page = book_view.get_selected (); + if (page == null) + { + page_move_left_menuitem.set_sensitive (false); + page_move_right_menuitem.set_sensitive (false); + } + else + { + var index = book.get_page_index (page); + page_move_left_menuitem.set_sensitive (index > 0); + page_move_right_menuitem.set_sensitive (index < book.get_n_pages () - 1); + } + } + + private void page_selected_cb (BookView view, Page? page) + { + if (page == null) + return; + + updating_page_menu = true; + + update_page_menu (); + + string? name = null; + if (page.has_crop ()) + { + // FIXME: Make more generic, move into page-size.c and reuse + var crop_name = page.get_named_crop (); + if (crop_name != null) + { + if (crop_name == "A4") + name = "a4_menuitem"; + else if (crop_name == "A5") + name = "a5_menuitem"; + else if (crop_name == "A6") + name = "a6_menuitem"; + else if (crop_name == "letter") + name = "letter_menuitem"; + else if (crop_name == "legal") + name = "legal_menuitem"; + else if (crop_name == "4x6") + name = "4x6_menuitem"; + } + else + name = "custom_crop_menuitem"; + } + else + name = "no_crop_menuitem"; + + var menuitem = (Gtk.RadioMenuItem) builder.get_object (name); + menuitem.set_active (true); + var toolbutton = (Gtk.ToggleToolButton) builder.get_object ("crop_toolbutton"); + toolbutton.set_active (page.has_crop ()); + + updating_page_menu = false; + } + + // FIXME: Duplicated from simple-scan.vala + private string? get_temporary_filename (string prefix, string extension) + { + /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and + * use the filename but it appears to work in practise */ + + var filename = "%sXXXXXX.%s".printf (prefix, extension); + string path; + try + { + var fd = FileUtils.open_tmp (filename, out path); + Posix.close (fd); + } + catch (Error e) + { + warning ("Error saving email attachment: %s", e.message); + return null; + } + + return path; + } + + private void show_page_cb (BookView view, Page page) + { + var path = get_temporary_filename ("scanned-page", "tiff"); + if (path == null) + return; + var file = File.new_for_path (path); + + try + { + page.save ("tiff", file); + } + catch (Error e) + { + show_error_dialog (/* Error message display when unable to save image for preview */ + _("Unable to save image for preview"), + e.message); + return; + } + + try + { + Gtk.show_uri (window.get_screen (), file.get_uri (), Gtk.get_current_event_time ()); + } + catch (Error e) + { + show_error_dialog (/* Error message display when unable to preview image */ + _("Unable to open image preview application"), + e.message); + } + } + + private void show_page_menu_cb (BookView view) + { + var menu = (Gtk.Menu) builder.get_object ("page_menu"); + menu.popup (null, null, null, 3, Gtk.get_current_event_time()); + } + + [CCode (cname = "G_MODULE_EXPORT rotate_left_button_clicked_cb", instance_pos = -1)] + public void rotate_left_button_clicked_cb (Gtk.Widget widget) + { + if (updating_page_menu) + return; + var page = book_view.get_selected (); + if (page != null) + page.rotate_left (); + } + + [CCode (cname = "G_MODULE_EXPORT rotate_right_button_clicked_cb", instance_pos = -1)] + public void rotate_right_button_clicked_cb (Gtk.Widget widget) + { + if (updating_page_menu) + return; + var page = book_view.get_selected (); + if (page != null) + page.rotate_right (); + } + + private void set_crop (string? crop_name) + { + crop_rotate_menuitem.set_sensitive (crop_name != null); + + if (updating_page_menu) + return; + + var page = book_view.get_selected (); + if (page == null) + return; + + if (crop_name == null) + { + page.set_no_crop (); + return; + } + else if (crop_name == "custom") + { + var width = page.get_width (); + var height = page.get_height (); + var crop_width = (int) (width * 0.8 + 0.5); + var crop_height = (int) (height * 0.8 + 0.5); + page.set_custom_crop (crop_width, crop_height); + page.move_crop ((width - crop_width) / 2, (height - crop_height) / 2); + } + else + page.set_named_crop (crop_name); + } + + [CCode (cname = "G_MODULE_EXPORT no_crop_menuitem_toggled_cb", instance_pos = -1)] + public void no_crop_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop (null); + } + + [CCode (cname = "G_MODULE_EXPORT custom_crop_menuitem_toggled_cb", instance_pos = -1)] + public void custom_crop_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("custom"); + } + + [CCode (cname = "G_MODULE_EXPORT crop_toolbutton_toggled_cb", instance_pos = -1)] + public void crop_toolbutton_toggled_cb (Gtk.ToggleToolButton widget) + { + if (updating_page_menu) + return; + + Gtk.RadioMenuItem menuitem; + if (widget.get_active ()) + menuitem = (Gtk.RadioMenuItem) builder.get_object ("custom_crop_menuitem"); + else + menuitem = (Gtk.RadioMenuItem) builder.get_object ("no_crop_menuitem"); + menuitem.set_active (true); + } + + [CCode (cname = "G_MODULE_EXPORT four_by_six_menuitem_toggled_cb", instance_pos = -1)] + public void four_by_six_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("4x6"); + } + + [CCode (cname = "G_MODULE_EXPORT legal_menuitem_toggled_cb", instance_pos = -1)] + public void legal_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("legal"); + } + + [CCode (cname = "G_MODULE_EXPORT letter_menuitem_toggled_cb", instance_pos = -1)] + public void letter_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("letter"); + } + + [CCode (cname = "G_MODULE_EXPORT a6_menuitem_toggled_cb", instance_pos = -1)] + public void a6_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("A6"); + } + + [CCode (cname = "G_MODULE_EXPORT a5_menuitem_toggled_cb", instance_pos = -1)] + public void a5_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("A5"); + } + + [CCode (cname = "G_MODULE_EXPORT a4_menuitem_toggled_cb", instance_pos = -1)] + public void a4_menuitem_toggled_cb (Gtk.CheckMenuItem widget) + { + if (widget.get_active ()) + set_crop ("A4"); + } + + [CCode (cname = "G_MODULE_EXPORT crop_rotate_menuitem_activate_cb", instance_pos = -1)] + public void crop_rotate_menuitem_activate_cb (Gtk.Widget widget) + { + var page = book_view.get_selected (); + if (page == null) + return; + page.rotate_crop (); + } + + [CCode (cname = "G_MODULE_EXPORT page_move_left_menuitem_activate_cb", instance_pos = -1)] + public void page_move_left_menuitem_activate_cb (Gtk.Widget widget) + { + var page = book_view.get_selected (); + var index = book.get_page_index (page); + if (index > 0) + book.move_page (page, index - 1); + + update_page_menu (); + } + + [CCode (cname = "G_MODULE_EXPORT page_move_right_menuitem_activate_cb", instance_pos = -1)] + public void page_move_right_menuitem_activate_cb (Gtk.Widget widget) + { + var page = book_view.get_selected (); + var index = book.get_page_index (page); + if (index < book.get_n_pages () - 1) + book.move_page (page, book.get_page_index (page) + 1); + + update_page_menu (); + } + + [CCode (cname = "G_MODULE_EXPORT page_delete_menuitem_activate_cb", instance_pos = -1)] + public void page_delete_menuitem_activate_cb (Gtk.Widget widget) + { + book_view.get_book ().delete_page (book_view.get_selected ()); + } + + [CCode (cname = "G_MODULE_EXPORT save_file_button_clicked_cb", instance_pos = -1)] + public void save_file_button_clicked_cb (Gtk.Widget widget) + { + save_document (false); + } + + [CCode (cname = "G_MODULE_EXPORT save_as_file_button_clicked_cb", instance_pos = -1)] + public void save_as_file_button_clicked_cb (Gtk.Widget widget) + { + save_document (true); + } + + private void draw_page (Gtk.PrintOperation operation, + Gtk.PrintContext print_context, + int page_number) + { + var context = print_context.get_cairo_context (); + var page = book.get_page (page_number); + + /* Rotate to same aspect */ + bool is_landscape = false; + if (print_context.get_width () > print_context.get_height ()) + is_landscape = true; + if (page.is_landscape () != is_landscape) + { + context.translate (print_context.get_width (), 0); + context.rotate (Math.PI_2); + } + + context.scale (print_context.get_dpi_x () / page.get_dpi (), + print_context.get_dpi_y () / page.get_dpi ()); + + var image = page.get_image (true); + Gdk.cairo_set_source_pixbuf (context, image, 0, 0); + context.paint (); + } + + [CCode (cname = "G_MODULE_EXPORT email_button_clicked_cb", instance_pos = -1)] + public void email_button_clicked_cb (Gtk.Widget widget) + { + email (document_hint); + } + + [CCode (cname = "G_MODULE_EXPORT print_button_clicked_cb", instance_pos = -1)] + public void print_button_clicked_cb (Gtk.Widget widget) + { + var print = new Gtk.PrintOperation (); + print.set_n_pages ((int) book.get_n_pages ()); + print.draw_page.connect (draw_page); + + try + { + print.run (Gtk.PrintOperationAction.PRINT_DIALOG, window); + } + catch (Error e) + { + warning ("Error printing: %s", e.message); + } + } + + [CCode (cname = "G_MODULE_EXPORT help_contents_menuitem_activate_cb", instance_pos = -1)] + public void help_contents_menuitem_activate_cb (Gtk.Widget widget) + { + try + { + Gtk.show_uri (window.get_screen (), "ghelp:simple-scan", Gtk.get_current_event_time ()); + } + catch (Error e) + { + show_error_dialog (/* Error message displayed when unable to launch help browser */ + _("Unable to open help file"), + e.message); + } + } + + [CCode (cname = "G_MODULE_EXPORT about_menuitem_activate_cb", instance_pos = -1)] + public void about_menuitem_activate_cb (Gtk.Widget widget) + { + string[] authors = { "Robert Ancell <robert.ancell@canonical.com>" }; + + /* The license this software is under (GPL3+) */ + string license = _("This program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <http://www.gnu.org/licenses/>."); + + /* Title of about dialog */ + string title = _("About Simple Scan"); + + /* Description of program */ + string description = _("Simple document scanning tool"); + + Gtk.show_about_dialog (window, + "title", title, + "program-name", "Simple Scan", + "version", Config.VERSION, + "comments", description, + "logo-icon-name", "scanner", + "authors", authors, + "translator-credits", _("translator-credits"), + "website", "https://launchpad.net/simple-scan", + "copyright", "Copyright © 2009-2011 Canonical Ltd.", + "license", license, + "wrap-license", true, + null); + } + + private bool on_quit () + { + if (!prompt_to_save (/* Text in dialog warning when a document is about to be lost */ + _("Save document before quitting?"), + /* Button in dialog to quit and discard unsaved document */ + _("Quit without Saving"))) + return false; + + var device = get_selected_device (); + int paper_width = 0, paper_height = 0; + get_paper_size (out paper_width, out paper_height); + + if (device != null) + settings.set_string ("selected-device", device); + settings.set_string ("document-type", document_hint); + settings.set_int ("text-dpi", get_text_dpi ()); + settings.set_int ("photo-dpi", get_photo_dpi ()); + settings.set_enum ("page-side", get_page_side ()); + settings.set_int ("paper-width", paper_width); + settings.set_int ("paper-height", paper_height); + settings.set_int ("window-width", window_width); + settings.set_int ("window-height", window_height); + settings.set_boolean ("window-is-maximized", window_is_maximized); + settings.set_enum ("scan-direction", default_page_scan_direction); + settings.set_int ("page-width", default_page_width); + settings.set_int ("page-height", default_page_height); + settings.set_int ("page-dpi", default_page_dpi); + + quit (); + + return true; + } + + [CCode (cname = "G_MODULE_EXPORT quit_menuitem_activate_cb", instance_pos = -1)] + public void quit_menuitem_activate_cb (Gtk.Widget widget) + { + on_quit (); + } + + [CCode (cname = "G_MODULE_EXPORT simple_scan_window_configure_event_cb", instance_pos = -1)] + public bool simple_scan_window_configure_event_cb (Gtk.Widget widget, Gdk.EventConfigure event) + { + if (!window_is_maximized) + { + window_width = event.width; + window_height = event.height; + } + + return false; + } + + private void info_bar_response_cb (Gtk.InfoBar widget, int response_id) + { + if (response_id == 1) + { + device_combo.grab_focus (); + preferences_dialog.present (); + } + else + { + have_error = false; + error_title = null; + error_text = null; + update_info_bar (); + } + } + + [CCode (cname = "G_MODULE_EXPORT simple_scan_window_window_state_event_cb", instance_pos = -1)] + public bool simple_scan_window_window_state_event_cb (Gtk.Widget widget, Gdk.EventWindowState event) + { + if ((event.changed_mask & Gdk.WindowState.MAXIMIZED) != 0) + window_is_maximized = (event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0; + return false; + } + + [CCode (cname = "G_MODULE_EXPORT window_delete_event_cb", instance_pos = -1)] + public bool window_delete_event_cb (Gtk.Widget widget, Gdk.Event event) + { + return !on_quit (); + } + + private void page_size_changed_cb (Page page) + { + default_page_width = page.get_width (); + default_page_height = page.get_height (); + default_page_dpi = page.get_dpi (); + } + + private void page_scan_direction_changed_cb (Page page) + { + default_page_scan_direction = page.get_scan_direction (); + } + + private void page_added_cb (Book book, Page page) + { + default_page_width = page.get_width (); + default_page_height = page.get_height (); + default_page_dpi = page.get_dpi (); + default_page_scan_direction = page.get_scan_direction (); + page.size_changed.connect (page_size_changed_cb); + page.scan_direction_changed.connect (page_scan_direction_changed_cb); + + update_page_menu (); + } + + private void page_removed_cb (Book book, Page page) + { + /* If this is the last page add a new blank one */ + if (book.get_n_pages () == 1) + add_default_page (); + + update_page_menu (); + } + + private void set_dpi_combo (Gtk.ComboBox combo, int default_dpi, int current_dpi) + { + var renderer = new Gtk.CellRendererText (); + combo.pack_start (renderer, true); + combo.add_attribute (renderer, "text", 1); + + var model = (Gtk.ListStore) combo.get_model (); + int[] scan_resolutions = {75, 150, 300, 600, 1200, 2400}; + foreach (var dpi in scan_resolutions) + { + string label; + if (dpi == default_dpi) + /* Preferences dialog: Label for default resolution in resolution list */ + label = _("%d dpi (default)").printf (dpi); + else if (dpi == 75) + /* Preferences dialog: Label for minimum resolution in resolution list */ + label = _("%d dpi (draft)").printf (dpi); + else if (dpi == 1200) + /* Preferences dialog: Label for maximum resolution in resolution list */ + label = _("%d dpi (high resolution)").printf (dpi); + else + /* Preferences dialog: Label for resolution value in resolution list (dpi = dots per inch) */ + label = _("%d dpi").printf (dpi); + + Gtk.TreeIter iter; + model.append (out iter); + model.set (iter, 0, dpi, 1, label, -1); + + if (dpi == current_dpi) + combo.set_active_iter (iter); + } + } + + private void needs_saving_cb (Book book) + { + save_menuitem.set_sensitive (book.get_needs_saving ()); + save_toolbutton.set_sensitive (book.get_needs_saving ()); + if (book.get_needs_saving ()) + save_as_menuitem.set_sensitive (true); + } + + private void load () + { + Gtk.IconTheme.get_default ().append_search_path (Config.ICON_DIR); + + Gtk.Window.set_default_icon_name ("scanner"); + + builder = new Gtk.Builder (); + var filename = Path.build_filename (Config.UI_DIR, "simple-scan.ui", null); + try + { + builder.add_from_file (filename); + } + catch (Error e) + { + critical ("Unable to load UI %s: %s\n", filename, e.message); + show_error_dialog (/* Title of dialog when cannot load required files */ + _("Files missing"), + /* Description in dialog when cannot load required files */ + _("Please check your installation")); + Posix.exit (Posix.EXIT_FAILURE); + } + builder.connect_signals (this); + + window = (Gtk.Window) builder.get_object ("simple_scan_window"); + main_vbox = (Gtk.VBox) builder.get_object ("main_vbox"); + page_move_left_menuitem = (Gtk.MenuItem) builder.get_object ("page_move_left_menuitem"); + page_move_right_menuitem = (Gtk.MenuItem) builder.get_object ("page_move_right_menuitem"); + page_delete_menuitem = (Gtk.MenuItem) builder.get_object ("page_delete_menuitem"); + crop_rotate_menuitem = (Gtk.MenuItem) builder.get_object ("crop_rotate_menuitem"); + save_menuitem = (Gtk.MenuItem) builder.get_object ("save_menuitem"); + save_as_menuitem = (Gtk.MenuItem) builder.get_object ("save_as_menuitem"); + save_toolbutton = (Gtk.ToolButton) builder.get_object ("save_toolbutton"); + stop_menuitem = (Gtk.MenuItem) builder.get_object ("stop_scan_menuitem"); + stop_toolbutton = (Gtk.ToolButton) builder.get_object ("stop_toolbutton"); + + text_toolbar_menuitem = (Gtk.RadioMenuItem) builder.get_object ("text_toolbutton_menuitem"); + text_menu_menuitem = (Gtk.RadioMenuItem) builder.get_object ("text_menuitem"); + photo_toolbar_menuitem = (Gtk.RadioMenuItem) builder.get_object ("photo_toolbutton_menuitem"); + photo_menu_menuitem = (Gtk.RadioMenuItem) builder.get_object ("photo_menuitem"); + + authorize_dialog = (Gtk.Dialog) builder.get_object ("authorize_dialog"); + authorize_label = (Gtk.Label) builder.get_object ("authorize_label"); + username_entry = (Gtk.Entry) builder.get_object ("username_entry"); + password_entry = (Gtk.Entry) builder.get_object ("password_entry"); + + preferences_dialog = (Gtk.Dialog) builder.get_object ("preferences_dialog"); + device_combo = (Gtk.ComboBox) builder.get_object ("device_combo"); + device_model = (Gtk.ListStore) device_combo.get_model (); + text_dpi_combo = (Gtk.ComboBox) builder.get_object ("text_dpi_combo"); + text_dpi_model = (Gtk.ListStore) text_dpi_combo.get_model (); + photo_dpi_combo = (Gtk.ComboBox) builder.get_object ("photo_dpi_combo"); + photo_dpi_model = (Gtk.ListStore) photo_dpi_combo.get_model (); + page_side_combo = (Gtk.ComboBox) builder.get_object ("page_side_combo"); + page_side_model = (Gtk.ListStore) page_side_combo.get_model (); + paper_size_combo = (Gtk.ComboBox) builder.get_object ("paper_size_combo"); + paper_size_model = (Gtk.ListStore) paper_size_combo.get_model (); + + /* Add InfoBar (not supported in Glade) */ + info_bar = new Gtk.InfoBar (); + info_bar.response.connect (info_bar_response_cb); + main_vbox.pack_start (info_bar, false, true, 0); + var hbox = new Gtk.HBox (false, 12); + var content_area = (Gtk.Container) info_bar.get_content_area (); + content_area.add (hbox); + hbox.show (); + + info_bar_image = new Gtk.Image.from_stock (Gtk.Stock.DIALOG_WARNING, Gtk.IconSize.DIALOG); + hbox.pack_start (info_bar_image, false, true, 0); + info_bar_image.show (); + + info_bar_label = new Gtk.Label (null); + info_bar_label.set_alignment (0.0f, 0.5f); + hbox.pack_start (info_bar_label, true, true, 0); + info_bar_label.show (); + + info_bar_close_button = (Gtk.Button) info_bar.add_button (Gtk.Stock.CLOSE, Gtk.ResponseType.CLOSE); + info_bar_change_scanner_button = (Gtk.Button) info_bar.add_button (/* Button in error infobar to open preferences dialog and change scanner */ + _("Change _Scanner"), 1); + + Gtk.TreeIter iter; + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 0, 1, 0, 2, + /* Combo box value for automatic paper size */ + _("Automatic"), -1); + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 1050, 1, 1480, 2, "A6", -1); + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 1480, 1, 2100, 2, "A5", -1); + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 2100, 1, 2970, 2, "A4", -1); + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 2159, 1, 2794, 2, "Letter", -1); + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 2159, 1, 3556, 2, "Legal", -1); + paper_size_model.append (out iter); + paper_size_model.set (iter, 0, 1016, 1, 1524, 2, "4×6", -1); + + var dpi = settings.get_int ("text-dpi"); + if (dpi <= 0) + dpi = DEFAULT_TEXT_DPI; + set_dpi_combo (text_dpi_combo, DEFAULT_TEXT_DPI, dpi); + dpi = settings.get_int ("photo-dpi"); + if (dpi <= 0) + dpi = DEFAULT_PHOTO_DPI; + set_dpi_combo (photo_dpi_combo, DEFAULT_PHOTO_DPI, dpi); + + var renderer = new Gtk.CellRendererText (); + device_combo.pack_start (renderer, true); + device_combo.add_attribute (renderer, "text", 1); + + renderer = new Gtk.CellRendererText (); + page_side_combo.pack_start (renderer, true); + page_side_combo.add_attribute (renderer, "text", 1); + set_page_side ((ScanType) settings.get_enum ("page-side")); + + renderer = new Gtk.CellRendererText (); + paper_size_combo.pack_start (renderer, true); + paper_size_combo.add_attribute (renderer, "text", 2); + var paper_width = settings.get_int ("paper-width"); + var paper_height = settings.get_int ("paper-height"); + set_paper_size (paper_width, paper_height); + + var device = settings.get_string ("selected-device"); + if (device != null) + { + if (find_scan_device (device, out iter)) + device_combo.set_active_iter (iter); + } + + var document_type = settings.get_string ("document-type"); + if (document_type != null) + set_document_hint (document_type); + + book_view = new BookView (book); + book_view.set_border_width (18); + main_vbox.pack_end (book_view, true, true, 0); + book_view.page_selected.connect (page_selected_cb); + book_view.show_page.connect (show_page_cb); + book_view.show_menu.connect (show_page_menu_cb); + book_view.show (); + + /* Find default page details */ + default_page_scan_direction = (ScanDirection) settings.get_enum ("scan-direction"); + default_page_width = settings.get_int ("page-width"); + if (default_page_width <= 0) + default_page_width = 595; + default_page_height = settings.get_int ("page-height"); + if (default_page_height <= 0) + default_page_height = 842; + default_page_dpi = settings.get_int ("page-dpi"); + if (default_page_dpi <= 0) + default_page_dpi = 72; + + /* Restore window size */ + window_width = settings.get_int ("window-width"); + if (window_width <= 0) + window_width = 600; + window_height = settings.get_int ("window-height"); + if (window_height <= 0) + window_height = 400; + debug ("Restoring window to %dx%d pixels", window_width, window_height); + window.set_default_size (window_width, window_height); + window_is_maximized = settings.get_boolean ("window-is-maximized"); + if (window_is_maximized) + { + debug ("Restoring window to maximized"); + window.maximize (); + } + + if (book.get_n_pages () == 0) + add_default_page (); + book.set_needs_saving (false); + book.needs_saving_changed.connect (needs_saving_cb); + } + + public Book get_book () + { + return book; + } + + public void set_selected_page (Page page) + { + book_view.select_page (page); + } + + public Page get_selected_page () + { + return book_view.get_selected (); + } + + public void set_scanning (bool scanning) + { + this.scanning = scanning; + page_delete_menuitem.set_sensitive (!scanning); + stop_menuitem.set_sensitive (scanning); + stop_toolbutton.set_sensitive (scanning); + } + + public void show_error (string error_title, string error_text, bool change_scanner_hint) + { + have_error = true; + this.error_title = error_title; + this.error_text = error_text; + error_change_scanner_hint = change_scanner_hint; + update_info_bar (); + } + + public void start () + { + window.show (); + } +} |