diff --git a/Makefile.in b/Makefile.in index 2f1f7e9ed..de8a46ab0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -329,6 +329,10 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WIC_CFLAGS = @WIC_CFLAGS@ +WIC_LIBS = @WIC_LIBS@ +WINHTTP_CFLAGS = @WINHTTP_CFLAGS@ +WINHTTP_LIBS = @WINHTTP_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ diff --git a/config.h.in b/config.h.in index 5ec1d066d..f92652832 100644 --- a/config.h.in +++ b/config.h.in @@ -168,9 +168,18 @@ /* Define to 1 if you have the 'm' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the 'ole32' library (-lole32). */ +#undef HAVE_LIBOLE32 + /* whether libpng is available */ #undef HAVE_LIBPNG +/* Define to 1 if you have the 'windowscodecs' library (-lwindowscodecs). */ +#undef HAVE_LIBWINDOWSCODECS + +/* Define to 1 if you have the 'winhttp' library (-lwinhttp). */ +#undef HAVE_LIBWINHTTP + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H @@ -302,6 +311,18 @@ /* Define to 1 if the system has the `deprecated' variable attribute */ #undef HAVE_VAR_ATTRIBUTE_DEPRECATED +/* whether Windows Imaging Component (WIC) is available */ +#undef HAVE_WIC + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINCODEC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H + +/* whether WinHTTP is available */ +#undef HAVE_WINHTTP + /* Define to 1 if the system has the type '_Bool'. */ #undef HAVE__BOOL diff --git a/configure b/configure index f9e45487c..224e70669 100755 --- a/configure +++ b/configure @@ -655,14 +655,18 @@ ac_unique_file="src/fromsixel.c" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS -HAVE_CURL_FALSE -HAVE_CURL_TRUE +HAVE_PYTHON_FALSE +HAVE_PYTHON_TRUE +HAVE_WIC_FALSE +HAVE_WIC_TRUE HAVE_PNG_FALSE HAVE_PNG_TRUE HAVE_JPEG_FALSE HAVE_JPEG_TRUE -HAVE_PYTHON_FALSE -HAVE_PYTHON_TRUE +HAVE_WINHTTP_FALSE +HAVE_WINHTTP_TRUE +HAVE_CURL_FALSE +HAVE_CURL_TRUE pkgpyexecdir pyexecdir pkgpythondir @@ -672,10 +676,14 @@ PYTHON_PREFIX PYTHON_PLATFORM PYTHON_VERSION PYTHON +WIC_LIBS +WIC_CFLAGS LIBPNG_LIBS LIBPNG_CFLAGS LIBJPEG_LIBS LIBJPEG_CFLAGS +WINHTTP_LIBS +WINHTTP_CFLAGS LIBCURL_LIBS LIBCURL_CFLAGS AM_CPPFLAGS @@ -850,6 +858,8 @@ with_gd with_libcurl with_jpeg with_png +with_wic +with_winhttp with_pkgconfigdir with_bashcompletiondir with_zshcompletiondir @@ -1546,6 +1556,10 @@ Optional Packages: --with-libcurl whether to build with libcurl (default: auto) --with-jpeg whether to build with libjpeg (default: auto) --with-png whether to build with libpng (default: auto) + --with-wic whether to build with Windows Imaging Component + (WIC), windows only (default: auto) + --with-winhttp whether to build with WinHTTP, windows only + (default: auto) --with-pkgconfigdir Use the specified pkgconfig dir (default is libdir/pkgconfig) --with-bashcompletiondir @@ -6549,7 +6563,7 @@ mingw* | windows* | pw32*) lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64)' + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64|coff-arm|coff-arm64|coff-i386|coff-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; @@ -12121,7 +12135,7 @@ cygwin* | mingw* | windows* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo $libname | $SED -e 's/^lib/msys-/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; @@ -14425,11 +14439,27 @@ esac fi -#AC_ARG_WITH([wic], -# [AS_HELP_STRING([--with-wic], -# [whether to build with windows WIC integration, windows only (default: no)])], -# [], -# [with_wic=no]) + +# Check whether --with-wic was given. +if test ${with_wic+y} +then : + withval=$with_wic; +else case e in #( + e) with_wic=auto ;; +esac +fi + + + +# Check whether --with-winhttp was given. +if test ${with_winhttp+y} +then : + withval=$with_winhttp; +else case e in #( + e) with_wic=auto ;; +esac +fi + # Check whether --with-pkgconfigdir was given. @@ -17284,20 +17314,11 @@ loaders="stb_image" have_curl="no" have_jpeg="no" have_png="no" -#have_wic="no" - -#if test x$with_wic != xno; then -# AC_CHECK_HEADERS([wincodec.h], [], -# [AC_MSG_ERROR([WIC integration: wincodec.h is not avilable.])]) -# AC_CHECK_LIB([ole32], [main], [], -# [AC_MSG_ERROR([WIC integration: library ole32 is not avilable.])]) -# AC_CHECK_LIB([uuid], [main], [], -# [AC_MSG_ERROR([WIC integration: library uuid is not avilable.])]) -# AC_CHECK_LIB([windowscodecs], [main], [], -# [AC_MSG_ERROR([WIC integration: library wincodecs is not avilable.])]) -# have_wic="yes" -#fi +have_wic="auto" +have_winhttp="auto" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gdk-pixbuf2" >&5 +printf %s "checking for gdk-pixbuf2... " >&6; } if test x$with_gdk_pixbuf2 != xno; then if test x${PKG_CONFIG} != x; then @@ -17394,7 +17415,8 @@ fi - +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GD" >&5 +printf %s "checking for GD... " >&6; } if test x$with_gd != xno; then CFLAGS_BACKUP=$CFLAGS LDFLAGS_BACKUP=$LDFLAGS @@ -18272,6 +18294,8 @@ fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcurl" >&5 +printf %s "checking for libcurl... " >&6; } if test x$with_libcurl != xno; then if test x$build = x$host; then CFLAGS_BACKUP=$CFLAGS @@ -18430,6 +18454,7 @@ fi fi fi if test x$have_curl = xyes; then + net="${net} libcurl" printf "%s\n" "#define HAVE_LIBCURL 1" >>confdefs.h @@ -18448,6 +18473,136 @@ fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for WinHTTP" >&5 +printf %s "checking for WinHTTP... " >&6; } +if test x$with_winhttp != xno; then + case "$host_os" in + mingw* | cygwin* | msys*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: checking on Windows host" >&5 +printf "%s\n" "checking on Windows host" >&6; } + CFLAGS_BACKUP="$CFLAGS" + LIBS_BACKUP="$LIBS" + if test x$with_png != xyes -a x$with_png != xauto; then + if test ! -d "$with_png"; then + as_fn_error $? "\"${with_png}\" is not directory" "$LINENO" 5 + fi + ADDED_CFLAGS="-I${with_winhttp}/include" + ADDED_LIBS="-L${with_winhttp}/lib -lwinhttp" + else + if test x${prefix} != x -a x${prefix} != xNONE; then + ADDED_CFLAGS="-I${prefix}/include" + ADDED_LIBS="-L${prefix}/lib -lwinhttp" + else + ADDED_CFLAGS="-I/usr/local/include" + ADDED_LIBS="-L/usr/local/lib -lwinhttp" + fi + fi + CFLAGS="${CFLAGS} ${ADDED_CFLAGS}" + LIBS="${LIBS} ${ADDED_LIBS}" + have_winhttp=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for WinHttpOpen in -lwinhttp" >&5 +printf %s "checking for WinHttpOpen in -lwinhttp... " >&6; } +if test ${ac_cv_lib_winhttp_WinHttpOpen+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_check_lib_save_LIBS=$LIBS +LIBS="-lwinhttp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. + The 'extern "C"' is for builds by C++ compilers; + although this is not generally supported in C code supporting it here + has little cost and some practical benefit (sr 110532). */ +#ifdef __cplusplus +extern "C" +#endif +char WinHttpOpen (void); +int +main (void) +{ +return WinHttpOpen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_winhttp_WinHttpOpen=yes +else case e in #( + e) ac_cv_lib_winhttp_WinHttpOpen=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_winhttp_WinHttpOpen" >&5 +printf "%s\n" "$ac_cv_lib_winhttp_WinHttpOpen" >&6; } +if test "x$ac_cv_lib_winhttp_WinHttpOpen" = xyes +then : + printf "%s\n" "#define HAVE_LIBWINHTTP 1" >>confdefs.h + + LIBS="-lwinhttp $LIBS" + +else case e in #( + e) have_winhttp=no + as_fn_error $? "library wincodecs is not avilable." "$LINENO" 5 ;; +esac +fi + +else case e in #( + e) have_winhttp=no + as_fn_error $? "windows.h or winhttp.h is not avilable." "$LINENO" 5 ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ;; + *) + have_winhttp=no + ;; + esac + CFLAGS=$CFLAGS_BACKUP + LIBS=$LIBS_BACKUP + if test "x$have_winhttp" = "xyes" +then : + +printf "%s\n" "#define HAVE_WINHTTP 1" >>confdefs.h + + net="${net} winhttp" + WINHTTP_CFLAGS=$ADDED_CFLAGS + WINHTTP_LIBS=$ADDED_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WinHTTP is available" >&5 +printf "%s\n" "$as_me: WinHTTP is available" >&6;} +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WinHTTP is not available" >&5 +printf "%s\n" "$as_me: WinHTTP is not available" >&6;} ;; +esac +fi +fi + + + if test x$with_jpeg != xno; then if test x$build = x$host; then CFLAGS_BACKUP=$CFLAGS @@ -18827,6 +18982,167 @@ fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Windows Imaging Component (WIC)" >&5 +printf %s "checking for Windows Imaging Component (WIC)... " >&6; } +if test x$with_wic != xno; then + case "$host_os" in + mingw* | cygwin* | msys*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: checking on Windows host" >&5 +printf "%s\n" "checking on Windows host" >&6; } + CFLAGS_BACKUP="$CFLAGS" + LIBS_BACKUP="$LIBS" + if test x$with_png != xyes -a x$with_png != xauto; then + if test ! -d "$with_png"; then + as_fn_error $? "\"${with_png}\" is not directory" "$LINENO" 5 + fi + ADDED_CFLAGS="-I${with_wic}/include" + ADDED_LIBS="-L${with_wic}/lib -lole32 -lwindowscodecs" + else + if test x${prefix} != x -a x${prefix} != xNONE; then + ADDED_CFLAGS="-I${prefix}/include" + ADDED_LIBS="-L${prefix}/lib -lole32 -lwindowscodecs" + else + ADDED_CFLAGS="-I/usr/local/include" + ADDED_LIBS="-L/usr/local/lib -lole32 -lwindowscodecs" + fi + fi + CFLAGS="${CFLAGS} ${ADDED_CFLAGS}" + LIBS="${LIBS} ${ADDED_LIBS}" + have_wic=yes + for ac_header in windows.h wincodec.h +do : + as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes" +then : + cat >>confdefs.h <<_ACEOF +#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1 +_ACEOF + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lole32" >&5 +printf %s "checking for main in -lole32... " >&6; } +if test ${ac_cv_lib_ole32_main+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_check_lib_save_LIBS=$LIBS +LIBS="-lole32 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main (void) +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_ole32_main=yes +else case e in #( + e) ac_cv_lib_ole32_main=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ole32_main" >&5 +printf "%s\n" "$ac_cv_lib_ole32_main" >&6; } +if test "x$ac_cv_lib_ole32_main" = xyes +then : + printf "%s\n" "#define HAVE_LIBOLE32 1" >>confdefs.h + + LIBS="-lole32 $LIBS" + +else case e in #( + e) have_wic=no + as_fn_error $? "library ole32 is not avilable." "$LINENO" 5 ;; +esac +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lwindowscodecs" >&5 +printf %s "checking for main in -lwindowscodecs... " >&6; } +if test ${ac_cv_lib_windowscodecs_main+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_check_lib_save_LIBS=$LIBS +LIBS="-lwindowscodecs $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main (void) +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_windowscodecs_main=yes +else case e in #( + e) ac_cv_lib_windowscodecs_main=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_windowscodecs_main" >&5 +printf "%s\n" "$ac_cv_lib_windowscodecs_main" >&6; } +if test "x$ac_cv_lib_windowscodecs_main" = xyes +then : + printf "%s\n" "#define HAVE_LIBWINDOWSCODECS 1" >>confdefs.h + + LIBS="-lwindowscodecs $LIBS" + +else case e in #( + e) have_wic=no + as_fn_error $? "library wincodecs is not avilable." "$LINENO" 5 ;; +esac +fi + +else case e in #( + e) have_wic=no + as_fn_error $? "windows.h or wincodec.h is not avilable." "$LINENO" 5 ;; +esac +fi + +done + ;; + *) + have_wic=no + ;; + esac + CFLAGS=$CFLAGS_BACKUP + LIBS=$LIBS_BACKUP + if test "x$have_wic" = "xyes" +then : + +printf "%s\n" "#define HAVE_WIC 1" >>confdefs.h + + loaders="${loaders} wic" + WIC_CFLAGS=$ADDED_CFLAGS + WIC_LIBS=$ADDED_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WIC is available" >&5 +printf "%s\n" "$as_me: WIC is available" >&6;} +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WIC is not available" >&5 +printf "%s\n" "$as_me: WIC is not available" >&6;} ;; +esac +fi +fi + + + have_python=no if test x$enable_python != xno; then @@ -19264,14 +19580,6 @@ printf "%s\n" "$am_cv_python_pyexecdir" >&6; } as_fn_error $? "python is not available" "$LINENO" 5 fi fi - if test x$have_python = xyes; then - HAVE_PYTHON_TRUE= - HAVE_PYTHON_FALSE='#' -else - HAVE_PYTHON_TRUE='#' - HAVE_PYTHON_FALSE= -fi - if test x$have_python = xyes; then message_python="$have_python: $pythondir" else @@ -19285,6 +19593,22 @@ fi python/Makefile.in src/Makefile.in tools/Makefile.in + if test x$have_curl = xyes; then + HAVE_CURL_TRUE= + HAVE_CURL_FALSE='#' +else + HAVE_CURL_TRUE='#' + HAVE_CURL_FALSE= +fi + + if test x$have_wic = xyes; then + HAVE_WINHTTP_TRUE= + HAVE_WINHTTP_FALSE='#' +else + HAVE_WINHTTP_TRUE='#' + HAVE_WINHTTP_FALSE= +fi + if test x$have_jpeg = xyes; then HAVE_JPEG_TRUE= HAVE_JPEG_FALSE='#' @@ -19301,12 +19625,20 @@ else HAVE_PNG_FALSE= fi - if test x$have_curl = xyes; then - HAVE_CURL_TRUE= - HAVE_CURL_FALSE='#' + if test x$have_wic = xyes; then + HAVE_WIC_TRUE= + HAVE_WIC_FALSE='#' else - HAVE_CURL_TRUE='#' - HAVE_CURL_FALSE= + HAVE_WIC_TRUE='#' + HAVE_WIC_FALSE= +fi + + if test x$have_python = xyes; then + HAVE_PYTHON_TRUE= + HAVE_PYTHON_FALSE='#' +else + HAVE_PYTHON_TRUE='#' + HAVE_PYTHON_FALSE= fi @@ -19486,8 +19818,12 @@ if test -z "${HAVE_GETOPT_LONG_TRUE}" && test -z "${HAVE_GETOPT_LONG_FALSE}"; th as_fn_error $? "conditional \"HAVE_GETOPT_LONG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_PYTHON_TRUE}" && test -z "${HAVE_PYTHON_FALSE}"; then - as_fn_error $? "conditional \"HAVE_PYTHON\" was never defined. +if test -z "${HAVE_CURL_TRUE}" && test -z "${HAVE_CURL_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CURL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_WINHTTP_TRUE}" && test -z "${HAVE_WINHTTP_FALSE}"; then + as_fn_error $? "conditional \"HAVE_WINHTTP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_JPEG_TRUE}" && test -z "${HAVE_JPEG_FALSE}"; then @@ -19498,8 +19834,12 @@ if test -z "${HAVE_PNG_TRUE}" && test -z "${HAVE_PNG_FALSE}"; then as_fn_error $? "conditional \"HAVE_PNG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_CURL_TRUE}" && test -z "${HAVE_CURL_FALSE}"; then - as_fn_error $? "conditional \"HAVE_CURL\" was never defined. +if test -z "${HAVE_WIC_TRUE}" && test -z "${HAVE_WIC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_WIC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PYTHON_TRUE}" && test -z "${HAVE_PYTHON_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PYTHON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -21674,7 +22014,7 @@ echo "" echo "libsixel was configured as follows" echo "" echo " Loader component : $loaders" -echo " libcurl integration : $have_curl" +echo " Network access : $net" echo " pkg-config dir : $pkgconfigdir" echo " Bash completion dir : $bashcompletiondir" echo " Zsh completion dir : $zshcompletiondir" diff --git a/configure.ac b/configure.ac index 0dfe26134..69a179bc6 100644 --- a/configure.ac +++ b/configure.ac @@ -110,11 +110,17 @@ AC_ARG_WITH([png], [], [with_png=auto]) -#AC_ARG_WITH([wic], -# [AS_HELP_STRING([--with-wic], -# [whether to build with windows WIC integration, windows only (default: no)])], -# [], -# [with_wic=no]) +AC_ARG_WITH([wic], + [AS_HELP_STRING([--with-wic], + [whether to build with Windows Imaging Component (WIC), windows only (default: auto)])], + [], + [with_wic=auto]) + +AC_ARG_WITH([winhttp], + [AS_HELP_STRING([--with-winhttp], + [whether to build with WinHTTP, windows only (default: auto)])], + [], + [with_wic=auto]) AC_ARG_WITH(pkgconfigdir, AS_HELP_STRING([--with-pkgconfigdir], @@ -326,20 +332,10 @@ loaders="stb_image" have_curl="no" have_jpeg="no" have_png="no" -#have_wic="no" - -#if test x$with_wic != xno; then -# AC_CHECK_HEADERS([wincodec.h], [], -# [AC_MSG_ERROR([WIC integration: wincodec.h is not avilable.])]) -# AC_CHECK_LIB([ole32], [main], [], -# [AC_MSG_ERROR([WIC integration: library ole32 is not avilable.])]) -# AC_CHECK_LIB([uuid], [main], [], -# [AC_MSG_ERROR([WIC integration: library uuid is not avilable.])]) -# AC_CHECK_LIB([windowscodecs], [main], [], -# [AC_MSG_ERROR([WIC integration: library wincodecs is not avilable.])]) -# have_wic="yes" -#fi +have_wic="auto" +have_winhttp="auto" +AC_MSG_CHECKING([for gdk-pixbuf2]) if test x$with_gdk_pixbuf2 != xno; then if test x${PKG_CONFIG} != x; then PKG_CHECK_MODULES([GDK_PIXBUF], @@ -364,7 +360,7 @@ fi AC_SUBST(GDK_PIXBUF_CFLAGS) AC_SUBST(GDK_PIXBUF_LIBS) - +AC_MSG_CHECKING([for GD]) if test x$with_gd != xno; then CFLAGS_BACKUP=$CFLAGS LDFLAGS_BACKUP=$LDFLAGS @@ -463,6 +459,7 @@ fi AC_SUBST(GD_CFLAGS) AC_SUBST(GD_LIBS) +AC_MSG_CHECKING([for libcurl]) if test x$with_libcurl != xno; then if test x$build = x$host; then CFLAGS_BACKUP=$CFLAGS @@ -503,6 +500,7 @@ if test x$with_libcurl != xno; then fi fi if test x$have_curl = xyes; then + net="${net} libcurl" AC_DEFINE(HAVE_LIBCURL, 1, [whether libcurl is available]) else if test x$with_libcurl != xauto; then @@ -516,6 +514,63 @@ fi AC_SUBST(LIBCURL_CFLAGS) AC_SUBST(LIBCURL_LIBS) +AC_MSG_CHECKING([for WinHTTP]) +if test x$with_winhttp != xno; then + case "$host_os" in + mingw* | cygwin* | msys*) + AC_MSG_RESULT([checking on Windows host]) + CFLAGS_BACKUP="$CFLAGS" + LIBS_BACKUP="$LIBS" + if test x$with_png != xyes -a x$with_png != xauto; then + if test ! -d "$with_png"; then + AC_MSG_ERROR(["${with_png}" is not directory]) + fi + ADDED_CFLAGS="-I${with_winhttp}/include" + ADDED_LIBS="-L${with_winhttp}/lib -lwinhttp" + else + if test x${prefix} != x -a x${prefix} != xNONE; then + ADDED_CFLAGS="-I${prefix}/include" + ADDED_LIBS="-L${prefix}/lib -lwinhttp" + else + ADDED_CFLAGS="-I/usr/local/include" + ADDED_LIBS="-L/usr/local/lib -lwinhttp" + fi + fi + CFLAGS="${CFLAGS} ${ADDED_CFLAGS}" + LIBS="${LIBS} ${ADDED_LIBS}" + have_winhttp=yes + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[]])], + [AC_CHECK_LIB([winhttp], + [WinHttpOpen], + [], + [have_winhttp=no + AC_MSG_ERROR([library wincodecs is not avilable.])])], + [have_winhttp=no + AC_MSG_ERROR([windows.h or winhttp.h is not avilable.])]) + ;; + *) + have_winhttp=no + ;; + esac + CFLAGS=$CFLAGS_BACKUP + LIBS=$LIBS_BACKUP + AS_IF([test "x$have_winhttp" = "xyes"], + [AC_DEFINE([HAVE_WINHTTP], + [1], + [whether WinHTTP is available]) + net="${net} winhttp" + WINHTTP_CFLAGS=$ADDED_CFLAGS + WINHTTP_LIBS=$ADDED_LIBS + AC_MSG_NOTICE([WinHTTP is available])], + [AC_MSG_NOTICE([WinHTTP is not available])]) +fi +AC_SUBST(WINHTTP_CFLAGS) +AC_SUBST(WINHTTP_LIBS) + if test x$with_jpeg != xno; then if test x$build = x$host; then CFLAGS_BACKUP=$CFLAGS @@ -630,6 +685,64 @@ fi AC_SUBST(LIBPNG_CFLAGS) AC_SUBST(LIBPNG_LIBS) +AC_MSG_CHECKING([for Windows Imaging Component (WIC)]) +if test x$with_wic != xno; then + case "$host_os" in + mingw* | cygwin* | msys*) + AC_MSG_RESULT([checking on Windows host]) + CFLAGS_BACKUP="$CFLAGS" + LIBS_BACKUP="$LIBS" + if test x$with_png != xyes -a x$with_png != xauto; then + if test ! -d "$with_png"; then + AC_MSG_ERROR(["${with_png}" is not directory]) + fi + ADDED_CFLAGS="-I${with_wic}/include" + ADDED_LIBS="-L${with_wic}/lib -lole32 -lwindowscodecs" + else + if test x${prefix} != x -a x${prefix} != xNONE; then + ADDED_CFLAGS="-I${prefix}/include" + ADDED_LIBS="-L${prefix}/lib -lole32 -lwindowscodecs" + else + ADDED_CFLAGS="-I/usr/local/include" + ADDED_LIBS="-L/usr/local/lib -lole32 -lwindowscodecs" + fi + fi + CFLAGS="${CFLAGS} ${ADDED_CFLAGS}" + LIBS="${LIBS} ${ADDED_LIBS}" + have_wic=yes + AC_CHECK_HEADERS([windows.h wincodec.h], + [AC_CHECK_LIB([ole32], + [main], + [], + [have_wic=no + AC_MSG_ERROR([library ole32 is not avilable.])]) + AC_CHECK_LIB([windowscodecs], + [main], + [], + [have_wic=no + AC_MSG_ERROR([library wincodecs is not avilable.])])], + [have_wic=no + AC_MSG_ERROR([windows.h or wincodec.h is not avilable.])]) + ;; + *) + have_wic=no + ;; + esac + CFLAGS=$CFLAGS_BACKUP + LIBS=$LIBS_BACKUP + AS_IF([test "x$have_wic" = "xyes"], + [AC_DEFINE([HAVE_WIC], + [1], + [whether Windows Imaging Component (WIC) is available]) + loaders="${loaders} wic" + WIC_CFLAGS=$ADDED_CFLAGS + WIC_LIBS=$ADDED_LIBS + AC_MSG_NOTICE([WIC is available])], + [AC_MSG_NOTICE([WIC is not available])]) +fi +AC_SUBST(WIC_CFLAGS) +AC_SUBST(WIC_LIBS) + have_python=no if test x$enable_python != xno; then AM_PATH_PYTHON([2.3], [have_python=yes], [have_python=no]) @@ -637,7 +750,6 @@ if test x$enable_python != xno; then AC_MSG_ERROR([python is not available]) fi fi -AM_CONDITIONAL([HAVE_PYTHON], [test x$have_python = xyes]) if test x$have_python = xyes; then message_python="$have_python: $pythondir" else @@ -651,9 +763,12 @@ AC_DEFUN([LS_UPDATE_TIMESTAMP], [ ]) LS_UPDATE_TIMESTAMP +AM_CONDITIONAL([HAVE_CURL], [test x$have_curl = xyes]) +AM_CONDITIONAL([HAVE_WINHTTP], [test x$have_wic = xyes]) AM_CONDITIONAL([HAVE_JPEG], [test x$have_jpeg = xyes]) AM_CONDITIONAL([HAVE_PNG], [test x$have_png = xyes]) -AM_CONDITIONAL([HAVE_CURL], [test x$have_curl = xyes]) +AM_CONDITIONAL([HAVE_WIC], [test x$have_wic = xyes]) +AM_CONDITIONAL([HAVE_PYTHON], [test x$have_python = xyes]) AC_CONFIG_FILES([Makefile libsixel.pc @@ -674,7 +789,7 @@ echo "" echo "libsixel was configured as follows" echo "" echo " Loader component : $loaders" -echo " libcurl integration : $have_curl" +echo " Network access : $net" echo " pkg-config dir : $pkgconfigdir" echo " Bash completion dir : $bashcompletiondir" echo " Zsh completion dir : $zshcompletiondir" @@ -685,3 +800,4 @@ echo " debugging : $enable_debug" echo " tests : $enable_tests" echo "" echo "" +dnl :vim set et: diff --git a/converters/Makefile.in b/converters/Makefile.in index 67d5f7bac..a20cdb45e 100644 --- a/converters/Makefile.in +++ b/converters/Makefile.in @@ -379,6 +379,10 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WIC_CFLAGS = @WIC_CFLAGS@ +WIC_LIBS = @WIC_LIBS@ +WINHTTP_CFLAGS = @WINHTTP_CFLAGS@ +WINHTTP_LIBS = @WINHTTP_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ diff --git a/converters/img2sixel.c b/converters/img2sixel.c index 1422bd6ca..d52829047 100644 --- a/converters/img2sixel.c +++ b/converters/img2sixel.c @@ -87,9 +87,15 @@ void show_version(void) "yes\n" #else "no\n" +#endif + " WIC: " +#ifdef HAVE_WIC + "yes\n" +#else + "no\n" #endif "\n" - "Copyright (C) 2014-2018 Hayaki Saito .\n" + "Copyright (C) 2014-2025 Hayaki Saito .\n" "\n" "Permission is hereby granted, free of charge, to any person obtaining a copy of\n" "this software and associated documentation files (the \"Software\"), to deal in\n" diff --git a/include/Makefile.in b/include/Makefile.in index 4af45d49d..8da12d4d9 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -262,6 +262,10 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WIC_CFLAGS = @WIC_CFLAGS@ +WIC_LIBS = @WIC_LIBS@ +WINHTTP_CFLAGS = @WINHTTP_CFLAGS@ +WINHTTP_LIBS = @WINHTTP_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ diff --git a/ltmain.sh b/ltmain.sh index 3e6a3db3a..f06d23f11 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -5335,7 +5335,7 @@ func_win32_libid () *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64)' >/dev/null; then + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64|coff-arm|coff-arm64|coff-i386|coff-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || @@ -5943,6 +5943,7 @@ EOF # include # include # ifdef __CYGWIN__ +# include # include # endif #endif @@ -5959,7 +5960,7 @@ EOF /* declarations of non-ANSI functions */ #if defined __MINGW32__ -# ifdef __STRICT_ANSI__ +# if defined(__STRICT_ANSI__) && !defined(__MINGW64_VERSION_MAJOR) || defined(_POSIX_) _CRTIMP int __cdecl _putenv (const char *); # endif #elif defined __CYGWIN__ @@ -6861,6 +6862,41 @@ EOF } # end: func_emit_cwrapperexe_src +# func_emit_exe_manifest +# emit a Win32 UAC manifest for executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_exe_manifest () +{ + cat < + + + + + + + + + + + + +EOF +} + # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () @@ -7715,6 +7751,7 @@ func_mode_link () # -static-libsan Link with static sanitizer runtimes (Clang) # -no-canonical-prefixes Do not expand any symbolic links # -fuse-ld=* Linker select flags for GCC + # -shared-* direct GCC to link specific libraries dynamically # -static-* direct GCC to link specific libraries statically # -fcilkplus Cilk Plus language extension features for C/C++ # -rtlib=* select c runtime lib with clang @@ -7729,6 +7766,7 @@ func_mode_link () -specs=*|-fsanitize=*|-fno-sanitize*|-shared-libsan|-static-libsan| \ -ffile-prefix-map=*|-fdebug-prefix-map=*|-fmacro-prefix-map=*|-fprofile-prefix-map=*| \ -fdiagnostics-color*|-frecord-gcc-switches| \ + -ffast-math|-fgnu-tm|-ftree-parallelize-loops=*|-funsafe-math-optimizations|-fvtable-verify*|-shared-*| \ -fuse-ld=*|-static-*|-fcilkplus|-Wa,*|-Werror|-Werror=*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result @@ -8228,8 +8266,15 @@ func_mode_link () fi case $linkmode in lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. + # Linking convenience modules and compiler provided static libraries + # into shared libraries is allowed, but linking other static + # libraries is non-portable. + case $deplib in + */libgcc*.$libext | */libclang_rt*.$libext) + deplibs="$deplib $deplibs" + continue + ;; + esac case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) @@ -8993,7 +9038,9 @@ func_mode_link () eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" - test "$absdir" != "$libdir" && \ + abs_inode=`ls -i "$deplib" | awk '{print $1}'` + lib_inode=`ls -i "$libdir/$(basename $deplib)" | awk '{print $1}'` + test "$abs_inode" != "$lib_inode" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir @@ -9701,6 +9748,15 @@ func_mode_link () a_deplib= break 2 fi + # Linking compiler provided static libraries into shared + # libraries is allowed, but linking other static libraries is + # non-portable. + case $potlib in + */libFortran*.$libext) + func_append newdeplibs " $potlib" + a_deplib= + ;; + esac done done fi @@ -10909,7 +10965,7 @@ func_mode_link () cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + trap "$RM $cwrappersource $cwrapper $cwrapper.manifest; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource @@ -10929,6 +10985,16 @@ func_mode_link () $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then + # Create the UAC manifests first if necessary (but the + # manifest files must have executable permission regardless). + case $output_name in + *instal*|*patch*|*setup*|*update*) + func_emit_exe_manifest > $cwrapper.manifest + func_emit_exe_manifest > $output_path/$objdir/$output_name.exe.manifest + chmod +x $cwrapper.manifest + chmod +x $output_path/$objdir/$output_name.exe.manifest + ;; + esac $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result @@ -11455,8 +11521,9 @@ func_mode_uninstall () # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" + func_append rmfiles " ${name}.manifest $objdir/${name}.manifest" if test yes = "$fast_install" && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" + func_append rmfiles " $odir/lt-$name $objdir/lt-${name}.manifest" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 8d323b3ee..ac9715675 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -2612,7 +2612,7 @@ cygwin* | mingw* | windows* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + soname_spec='`echo $libname | $SED -e 's/^lib/msys-/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; @@ -3601,7 +3601,7 @@ mingw* | windows* | pw32*) lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64)' + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64|coff-arm|coff-arm64|coff-i386|coff-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; @@ -7708,7 +7708,7 @@ if AC_TRY_EVAL(ac_compile); then for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in - -L* | -R* | -l*) + -L* | -R* | -l* | */libclang_rt.*.a) # Some compilers place space between "-{L,R,l}" and the path. # Remove the space. if test x-L = x"$p" || diff --git a/python/Makefile.in b/python/Makefile.in index 219c99fcb..23a63c2e8 100644 --- a/python/Makefile.in +++ b/python/Makefile.in @@ -250,6 +250,10 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WIC_CFLAGS = @WIC_CFLAGS@ +WIC_LIBS = @WIC_LIBS@ +WINHTTP_CFLAGS = @WINHTTP_CFLAGS@ +WINHTTP_LIBS = @WINHTTP_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ diff --git a/src/Makefile.am b/src/Makefile.am index a59f38ad0..287e49976 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -57,17 +57,21 @@ libsixel_la_SOURCES = \ libsixel_la_CPPFLAGS = -I$(top_builddir)/include/ libsixel_la_CFLAGS = $(CFLAGS) $(AM_CFLAGS) $(MAYBE_COVERAGE) \ $(LIBCURL_CFLAGS) \ + $(WINHTTP_CFLAGS) \ $(LIBPNG_CFLAGS) \ $(LIBJPEG_CFLAGS) \ $(GDK_PIXBUF_CFLAGS) \ - $(GD_CFLAGS) + $(GD_CFLAGS) \ + $(WIC_CFLAGS) libsixel_la_LDFLAGS = -no-undefined -version-info $(LS_LTVERSION) libsixel_la_LIBADD = -lm \ $(LIBCURL_LIBS) \ + $(WINHTTP_LIBS) \ $(LIBPNG_LIBS) \ $(LIBJPEG_LIBS) \ $(GDK_PIXBUF_LIBS) \ - $(GD_LIBS) + $(GD_LIBS) \ + $(WIC_LIBS) if COND_TESTS noinst_PROGRAMS = tests diff --git a/src/Makefile.in b/src/Makefile.in index e78faa140..66a2719a0 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -137,6 +137,7 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man5dir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libsixel_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libsixel_la_OBJECTS = libsixel_la-output.lo \ @@ -340,6 +341,10 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WIC_CFLAGS = @WIC_CFLAGS@ +WIC_LIBS = @WIC_LIBS@ +WINHTTP_CFLAGS = @WINHTTP_CFLAGS@ +WINHTTP_LIBS = @WINHTTP_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -451,18 +456,22 @@ libsixel_la_SOURCES = \ libsixel_la_CPPFLAGS = -I$(top_builddir)/include/ libsixel_la_CFLAGS = $(CFLAGS) $(AM_CFLAGS) $(MAYBE_COVERAGE) \ $(LIBCURL_CFLAGS) \ + $(WINHTTP_CFLAGS) \ $(LIBPNG_CFLAGS) \ $(LIBJPEG_CFLAGS) \ $(GDK_PIXBUF_CFLAGS) \ - $(GD_CFLAGS) + $(GD_CFLAGS) \ + $(WIC_CFLAGS) libsixel_la_LDFLAGS = -no-undefined -version-info $(LS_LTVERSION) libsixel_la_LIBADD = -lm \ $(LIBCURL_LIBS) \ + $(WINHTTP_LIBS) \ $(LIBPNG_LIBS) \ $(LIBJPEG_LIBS) \ $(GDK_PIXBUF_LIBS) \ - $(GD_LIBS) + $(GD_LIBS) \ + $(WIC_LIBS) @COND_TESTS_TRUE@tests_SOURCES = $(srcdir)/tests.c @COND_TESTS_TRUE@tests_CPPFLAGS = -I$(top_builddir)/include/ \ diff --git a/src/chunk.c b/src/chunk.c index bd03adf1f..2f4883b44 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -312,16 +312,260 @@ sixel_chunk_from_file( return status; } +#if HAVE_WINHTTP +#define UNICODE +#define _UNICODE +#include +#include -/* get chunk of specified resource over libcurl function */ +static wchar_t * +utf8_to_wide(char const *s) { + wchar_t *w; + int n; + + n = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); + if (n <= 0) { + return NULL; + } + w = (wchar_t*) malloc(sizeof(wchar_t) * n); + if (!w) { + return NULL; + } + if (!MultiByteToWideChar(CP_UTF8, 0, s, -1, w, n)) { + free(w); + return NULL; + } + + return w; +} +#endif /* HAVE_WINHTTP */ + +#if HAVE_WINHTTP static SIXELSTATUS -sixel_chunk_from_url( +sixel_chunk_from_url_with_winhttp( + char const /* in */ *url, + sixel_chunk_t /* in */ *pchunk, + int /* in */ finsecure +) +{ + SIXELSTATUS status = SIXEL_FALSE; + unsigned long const timeout_ms = 10000; + wchar_t *wua = NULL; + wchar_t *wurl = NULL; + wchar_t hostname[2048]; + wchar_t path[4096]; + WINHTTP_PROXY_INFO pinfo; + WINHTTP_AUTOPROXY_OPTIONS apo; + HINTERNET hSession = NULL; + HINTERNET hConnect = NULL; + HINTERNET hRequest = NULL; + INTERNET_PORT port; + BOOL bRet; + DWORD dwStatus = 0; + DWORD dwSize = sizeof(dwStatus); + DWORD dwFlags; + DWORD dwRead = 0; + DWORD dwAvail = 0; + DWORD dwEnable = 1; + URL_COMPONENTS uc; + void *p = NULL; + + wua = utf8_to_wide("libsixel/" LIBSIXEL_VERSION); + if (wua == NULL) { + goto end; + } + + wurl = utf8_to_wide(url); + if (wurl == NULL) { + goto end; + } + + RtlZeroMemory(&uc, sizeof(uc)); + uc.dwStructSize = sizeof(uc); + uc.lpszHostName = hostname; + uc.dwHostNameLength = sizeof(hostname) / sizeof(hostname[0]); + uc.lpszUrlPath = path; + uc.dwUrlPathLength = sizeof(path) / sizeof(path[0]); + uc.lpszExtraInfo = NULL; + uc.dwExtraInfoLength = 0; + + bRet = WinHttpCrackUrl(wurl, 0, 0, &uc); + if (! bRet || ! uc.lpszHostName) { + goto end; + } + + if (uc.nScheme != INTERNET_SCHEME_HTTPS && + uc.nScheme != INTERNET_SCHEME_HTTP) { + /* unavailable protocol */ + status = SIXEL_BAD_ARGUMENT; + goto end; + } + + port = uc.nPort; + if (! port) { + if (uc.nScheme == INTERNET_SCHEME_HTTPS) { + port = 443; + } else if (uc.nScheme == INTERNET_SCHEME_HTTP) { + port = 80; + } + } + + hSession = WinHttpOpen(wua, + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, 0); + if (!hSession) { + goto end; + } + + if (timeout_ms) { + WinHttpSetTimeouts( + hSession, + timeout_ms, /* dwResolveTimeout */ + timeout_ms, /* dwConnectTimeout */ + timeout_ms, /* dwSendTimeout */ + timeout_ms); /* dwReceiveTimeout */ + } + + hConnect = WinHttpConnect(hSession, uc.lpszHostName, port, 0); + if (!hConnect) { + goto end; + } + + dwFlags = (uc.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0; + + hRequest = WinHttpOpenRequest(hConnect, L"GET", + uc.lpszUrlPath && *uc.lpszUrlPath ? + uc.lpszUrlPath : + L"/", + NULL, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + dwFlags); + if (!hRequest) { + goto end; + } + WinHttpSetOption(hRequest, WINHTTP_OPTION_ENABLE_FEATURE, + &dwEnable, sizeof(dwEnable)); + if (finsecure) { + dwFlags = 0; + dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA; + dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; + dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID; + WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, + &dwFlags, sizeof(dwFlags)); + } + + RtlZeroMemory(&apo, sizeof(apo)); + apo.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT; + apo.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DHCP; + apo.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DNS_A; + apo.fAutoLogonIfChallenged = TRUE; + + RtlZeroMemory(&pinfo, sizeof(pinfo)); + if (WinHttpGetProxyForUrl(hSession, wurl, &apo, &pinfo)) { + WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, + &pinfo, sizeof(pinfo)); + if (pinfo.lpszProxy) { + GlobalFree(pinfo.lpszProxy); + } + if (pinfo.lpszProxyBypass) { + GlobalFree(pinfo.lpszProxyBypass); + } + } + + bRet = WinHttpSendRequest(hRequest, + WINHTTP_NO_ADDITIONAL_HEADERS, 0, + WINHTTP_NO_REQUEST_DATA, 0, 0, 0); + if (!bRet) { + goto end; + } + + bRet = WinHttpReceiveResponse(hRequest, NULL); + if (!bRet) { + goto end; + } + + (void) WinHttpQueryHeaders(hRequest, + WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + &dwStatus, + &dwSize, + WINHTTP_NO_HEADER_INDEX); + + for (;;) { + if (! WinHttpQueryDataAvailable(hRequest, &dwAvail)) { + goto err; + } + if (dwAvail == 0) { + break; + } + if (pchunk->size + dwAvail > pchunk->max_size) { + do { + pchunk->max_size *= 2; + } while (pchunk->max_size < pchunk->size + dwAvail); + p = sixel_allocator_realloc( + pchunk->allocator, pchunk->buffer, pchunk->max_size); + if (! p) { + goto err; + } + pchunk->buffer = p; + } + + dwRead = 0; + if (! WinHttpReadData(hRequest, + pchunk->buffer + pchunk->size, + dwAvail, &dwRead)) { + goto err; + } + if (dwRead == 0) { + break; + } + + pchunk->size += dwRead; + } + + status = SIXEL_OK; + + goto end; + +err: + if (pchunk->buffer) { + free(pchunk->buffer); + } + +end: + if (hRequest) { + WinHttpCloseHandle(hRequest); + } + if (hConnect) { + WinHttpCloseHandle(hConnect); + } + if (hSession) { + WinHttpCloseHandle(hSession); + } + if (wua) { + free(wua); + } + if (wurl) { + free(wurl); + } + + status = SIXEL_OK; + + return status; +} +# endif /* HAVE_WINHTTP */ + + +# if HAVE_LIBCURL +static SIXELSTATUS +sixel_chunk_from_url_with_curl( char const /* in */ *url, sixel_chunk_t /* in */ *pchunk, int /* in */ finsecure) { SIXELSTATUS status = SIXEL_FALSE; -# ifdef HAVE_LIBCURL CURL *curl = NULL; CURLcode code; @@ -400,24 +644,49 @@ sixel_chunk_from_url( } status = SIXEL_OK; -# else - (void) url; - (void) pchunk; - (void) finsecure; - sixel_helper_set_additional_message( - "To specify URI schemes, you have to " - "configure this program with --with-libcurl " - "option at compile time.\n"); - status = SIXEL_NOT_IMPLEMENTED; - goto end; -# endif /* HAVE_LIBCURL */ end: -# ifdef HAVE_LIBCURL if (curl) { curl_easy_cleanup(curl); } + + return status; +} # endif /* HAVE_LIBCURL */ + +/* get chunk of specified resource over libcurl function */ +static SIXELSTATUS +sixel_chunk_from_url( + char const /* in */ *url, + sixel_chunk_t /* in */ *pchunk, + int /* in */ finsecure) +{ + SIXELSTATUS status = SIXEL_NOT_IMPLEMENTED; +#if HAVE_WINHTTP + status = sixel_chunk_from_url_with_winhttp(url, pchunk, finsecure); + if (SIXEL_SUCCEEDED(status)) { + return status; + } +#endif /* HAVE_WINHTTP */ + +#if HAVE_LIBCURL + status = sixel_chunk_from_url_with_curl(url, pchunk, finsecure); + if (SIXEL_SUCCEEDED(status)) { + return status; + } +#endif /* HAVE_LIBCURL */ + +#if !defined(HAVE_WINHTTP) && !defined(HAVE_LIBCURL) + (void) url; + (void) pchunk; + (void) finsecure; + sixel_helper_set_additional_message( + "To specify URI schemes, you must configure this program " + "at compile time using either the --with-libcurl option " + "or the --with-winhttp (only available on Windows) option.\n"); + status = SIXEL_NOT_IMPLEMENTED; +#endif /* !defined(HAVE_WINHTTP) && !defined(HAVE_LIBCURL) */ + return status; } diff --git a/src/loader.c b/src/loader.c index a7e98903c..b4d481774 100644 --- a/src/loader.c +++ b/src/loader.c @@ -1189,7 +1189,7 @@ load_with_gdkpixbuf( } #endif /* HAVE_GDK_PIXBUF2 */ -#ifdef HAVE_GD +#if HAVE_GD static int detect_file_format(int len, unsigned char *data) { @@ -1251,7 +1251,9 @@ detect_file_format(int len, unsigned char *data) return (-1); } +#endif /* HAVE_GD */ +#if HAVE_GD static SIXELSTATUS load_with_gd( @@ -1389,6 +1391,178 @@ load_with_gd( #endif /* HAVE_GD */ +#if HAVE_WIC + +#include +#include + +SIXELSTATUS +load_with_wic( + sixel_chunk_t const /* in */ *pchunk, /* image data */ + int /* in */ fstatic, /* static */ + int /* in */ fuse_palette, /* whether to use palette if possible */ + int /* in */ reqcolors, /* reqcolors */ + unsigned char /* in */ *bgcolor, /* background color */ + int /* in */ loop_control, /* one of enum loop_control */ + sixel_load_image_function /* in */ fn_load, /* callback */ + void /* in/out */ *context /* private data for callback */ +) +{ + HRESULT hr = E_FAIL; + SIXELSTATUS status = SIXEL_FALSE; + IWICImagingFactory *factory = NULL; + IWICStream *stream = NULL; + IWICBitmapDecoder *decoder = NULL; + IWICBitmapFrameDecode *wicframe = NULL; + IWICFormatConverter *conv = NULL; + IWICBitmapSource *src = NULL; + sixel_frame_t *frame = NULL; + int comp = 4; + + (void) fstatic; + (void) reqcolors; + (void) bgcolor; + (void) loop_control; + + if (fuse_palette) { + return status; + } + + if (memcmp("GIF", pchunk->buffer, 3) == 0) { + return status; + } + + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr) && hr != RPC_E_CHANGED_MODE) { + return status; + } + + status = sixel_frame_new(&frame, pchunk->allocator); + if (SIXEL_FAILED(status)) { + goto end; + } + + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICImagingFactory, (void**)&factory); + if (FAILED(hr)) { + goto end; + } + + hr = factory->lpVtbl->CreateStream(factory, &stream); + if (FAILED(hr)) { + goto end; + } + + hr = stream->lpVtbl->InitializeFromMemory( + stream, (BYTE*)pchunk->buffer, (DWORD)pchunk->size); + if (FAILED(hr)) { + goto end; + } + + hr = factory->lpVtbl->CreateDecoderFromStream( + factory, (IStream*)stream, NULL, + WICDecodeMetadataCacheOnDemand, &decoder); + if (FAILED(hr)) { + goto end; + } + + hr = decoder->lpVtbl->GetFrame(decoder, 0, &wicframe); + if (FAILED(hr)) { + goto end; + } + + hr = factory->lpVtbl->CreateFormatConverter(factory, &conv); + if (FAILED(hr)) { + goto end; + } + + hr = conv->lpVtbl->Initialize(conv, (IWICBitmapSource*)wicframe, + &GUID_WICPixelFormat32bppRGBA, + WICBitmapDitherTypeNone, NULL, 0.0, + WICBitmapPaletteTypeCustom); + if (FAILED(hr)) { + goto end; + } + + src = (IWICBitmapSource*)conv; + + hr = src->lpVtbl->GetSize( + src, (UINT *)&frame->width, (UINT *)&frame->height); + if (FAILED(hr)) { + goto end; + } + + /* check size */ + if (frame->width <= 0) { + sixel_helper_set_additional_message( + "load_with_wic: an invalid width parameter detected."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (frame->height <= 0) { + sixel_helper_set_additional_message( + "load_with_wic: an invalid width parameter detected."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (frame->width > SIXEL_WIDTH_LIMIT) { + sixel_helper_set_additional_message( + "load_with_wic: given width parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (frame->height > SIXEL_HEIGHT_LIMIT) { + sixel_helper_set_additional_message( + "load_with_wic: given height parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + + frame->pixelformat = SIXEL_PIXELFORMAT_RGBA8888; + frame->pixels = sixel_allocator_malloc( + pchunk->allocator, + (size_t)(frame->height * frame->width * comp)); + + WICRect rc = (WICRect){ 0, 0, (INT)frame->width, (INT)frame->height }; + hr = src->lpVtbl->CopyPixels( + src, + &rc, /* prc */ + frame->width * comp, /* cbStride */ + (UINT)frame->width * frame->height * comp, /* cbBufferSize */ + frame->pixels); /* pbBuffer */ + if (FAILED(hr)) { + goto end; + } + + status = fn_load(frame, context); + if (SIXEL_FAILED(status)) { + goto end; + } + +end: + if (conv) { + conv->lpVtbl->Release(conv); + } + if (wicframe) { + wicframe->lpVtbl->Release(wicframe); + } + if (stream) { + stream->lpVtbl->Release(stream); + } + if (factory) { + factory->lpVtbl->Release(factory); + } + + CoUninitialize(); + + if (FAILED(hr)) { + return SIXEL_FALSE; + } + + return SIXEL_OK; +} + +#endif /* HAVE_WIC */ /* load image from file */ @@ -1434,6 +1608,18 @@ sixel_helper_load_image_file( } status = SIXEL_FALSE; +#ifdef HAVE_WIC + if (SIXEL_FAILED(status)) { + status = load_with_wic(pchunk, + fstatic, + fuse_palette, + reqcolors, + bgcolor, + loop_control, + fn_load, + context); + } +#endif /* HAVE_WIC */ #ifdef HAVE_GDK_PIXBUF2 if (SIXEL_FAILED(status)) { status = load_with_gdkpixbuf(pchunk, diff --git a/tools/Makefile.in b/tools/Makefile.in index a4f68999e..27f05b0c9 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -245,6 +245,10 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WIC_CFLAGS = @WIC_CFLAGS@ +WIC_LIBS = @WIC_LIBS@ +WINHTTP_CFLAGS = @WINHTTP_CFLAGS@ +WINHTTP_LIBS = @WINHTTP_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@