diff options
Diffstat (limited to 'plug-ins/script-fu')
111 files changed, 29809 insertions, 0 deletions
diff --git a/plug-ins/script-fu/Makefile.am b/plug-ins/script-fu/Makefile.am new file mode 100644 index 0000000..46ad336 --- /dev/null +++ b/plug-ins/script-fu/Makefile.am @@ -0,0 +1,117 @@ +## Process this file with automake to produce Makefile.in + +if PLATFORM_OSX +xobjective_c = "-xobjective-c" +xobjective_cxx = "-xobjective-c++" +xnone = "-xnone" +framework_cocoa = -framework Cocoa +endif + +if OS_WIN32 +mwindows = -mwindows +WINSOCK_LIBS = -lws2_32 +else +libm = -lm +endif + +libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la +libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la +libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la +libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la +libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la +libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la +libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la $(libm) + +libtinyscheme=tinyscheme/libtinyscheme.a $(libm) +libftx=ftx/libftx.a + +if HAVE_WINDRES +include $(top_srcdir)/build/windows/gimprc-plug-ins.rule +script_fu_RC = script-fu.rc.o +endif + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(GTK_CFLAGS) \ + $(GEGL_CFLAGS) \ + -I$(includedir) \ + -DSTANDALONE=0 \ + -DUSE_INTERFACE=1 \ + -DUSE_STRLWR=0 + +AM_CFLAGS = \ + $(xobjective_c) + +AM_CXXFLAGS = \ + $(xobjective_cxx) + +AM_LDFLAGS = \ + $(mwindows) \ + $(framework_cocoa) \ + $(xnone) + +SUBDIRS = tinyscheme ftx scripts + + +libexecdir = $(gimpplugindir)/plug-ins/script-fu + +libexec_PROGRAMS = script-fu + +script_fu_SOURCES = \ + script-fu-types.h \ + script-fu-enums.h \ + \ + script-fu.c \ + script-fu-console.c \ + script-fu-console.h \ + script-fu-eval.c \ + script-fu-eval.h \ + script-fu-interface.c \ + script-fu-interface.h \ + script-fu-text-console.h \ + script-fu-text-console.c \ + script-fu-intl.h \ + script-fu-regex.c \ + script-fu-regex.h \ + script-fu-script.c \ + script-fu-script.h \ + script-fu-scripts.c \ + script-fu-scripts.h \ + script-fu-server.c \ + script-fu-server.h \ + script-fu-utils.c \ + script-fu-utils.h \ + scheme-wrapper.c \ + scheme-wrapper.h + +LDADD = \ + $(libgimpui) \ + $(libgimpwidgets) \ + $(libgimpconfig) \ + $(libgimpmath) \ + $(libgimp) \ + $(libgimpcolor) \ + $(libgimpbase) \ + $(libtinyscheme) \ + $(libftx) \ + $(GTK_LIBS) \ + $(SOCKET_LIBS) \ + $(WINSOCK_LIBS) \ + $(RT_LIBS) \ + $(INTLLIBS) \ + $(script_fu_RC) + + +# Perform static analysis on all *.scm files and look for usage of +# deprecated pdb procedures +check-for-deprecated-procedures-in-script-fu: + @echo "Looking for deprecated procedures in *.scm files" + @scm_files=`find $(top_srcdir)/plug-ins/script-fu -name "*.scm"`; \ + deprecated_procs=`$(top_builddir)/app/gimp-$(GIMP_APP_VERSION)$(EXEEXT) --dump-pdb-procedures-deprecated`; \ + for scm_file in $$scm_files; do \ + for proc in $$deprecated_procs; do \ + if grep -Eq "^([^;]*[[:blank:](])?$$proc([[:blank:])]|$$)" $$scm_file; then \ + echo "$${scm_file} uses deprecated procedure '$${proc}'"; \ + fi \ + done \ + done diff --git a/plug-ins/script-fu/Makefile.in b/plug-ins/script-fu/Makefile.in new file mode 100644 index 0000000..493b4f7 --- /dev/null +++ b/plug-ins/script-fu/Makefile.in @@ -0,0 +1,1225 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Version resources for Microsoft Windows + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +libexec_PROGRAMS = script-fu$(EXEEXT) +subdir = plug-ins/script-fu +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am_script_fu_OBJECTS = script-fu.$(OBJEXT) script-fu-console.$(OBJEXT) \ + script-fu-eval.$(OBJEXT) script-fu-interface.$(OBJEXT) \ + script-fu-text-console.$(OBJEXT) script-fu-regex.$(OBJEXT) \ + script-fu-script.$(OBJEXT) script-fu-scripts.$(OBJEXT) \ + script-fu-server.$(OBJEXT) script-fu-utils.$(OBJEXT) \ + scheme-wrapper.$(OBJEXT) +script_fu_OBJECTS = $(am_script_fu_OBJECTS) +script_fu_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la \ + $(am__DEPENDENCIES_1) +am__DEPENDENCIES_3 = tinyscheme/libtinyscheme.a $(am__DEPENDENCIES_1) +script_fu_DEPENDENCIES = $(libgimpui) $(libgimpwidgets) \ + $(libgimpconfig) $(am__DEPENDENCIES_2) $(libgimp) \ + $(libgimpcolor) $(libgimpbase) $(am__DEPENDENCIES_3) $(libftx) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(script_fu_RC) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/scheme-wrapper.Po \ + ./$(DEPDIR)/script-fu-console.Po ./$(DEPDIR)/script-fu-eval.Po \ + ./$(DEPDIR)/script-fu-interface.Po \ + ./$(DEPDIR)/script-fu-regex.Po ./$(DEPDIR)/script-fu-script.Po \ + ./$(DEPDIR)/script-fu-scripts.Po \ + ./$(DEPDIR)/script-fu-server.Po \ + ./$(DEPDIR)/script-fu-text-console.Po \ + ./$(DEPDIR)/script-fu-utils.Po ./$(DEPDIR)/script-fu.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(script_fu_SOURCES) +DIST_SOURCES = $(script_fu_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build/windows/gimprc-plug-ins.rule \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = $(gimpplugindir)/plug-ins/script-fu +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@PLATFORM_OSX_TRUE@xobjective_c = "-xobjective-c" +@PLATFORM_OSX_TRUE@xobjective_cxx = "-xobjective-c++" +@PLATFORM_OSX_TRUE@xnone = "-xnone" +@PLATFORM_OSX_TRUE@framework_cocoa = -framework Cocoa +@OS_WIN32_TRUE@mwindows = -mwindows +@OS_WIN32_TRUE@WINSOCK_LIBS = -lws2_32 +@OS_WIN32_FALSE@libm = -lm +libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la +libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la +libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la +libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la +libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la +libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la +libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la $(libm) +libtinyscheme = tinyscheme/libtinyscheme.a $(libm) +libftx = ftx/libftx.a +@HAVE_WINDRES_TRUE@GIMPPLUGINRC = $(top_builddir)/build/windows/gimp-plug-ins.rc +@HAVE_WINDRES_TRUE@script_fu_RC = script-fu.rc.o +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(GTK_CFLAGS) \ + $(GEGL_CFLAGS) \ + -I$(includedir) \ + -DSTANDALONE=0 \ + -DUSE_INTERFACE=1 \ + -DUSE_STRLWR=0 + +AM_CFLAGS = \ + $(xobjective_c) + +AM_CXXFLAGS = \ + $(xobjective_cxx) + +AM_LDFLAGS = \ + $(mwindows) \ + $(framework_cocoa) \ + $(xnone) + +SUBDIRS = tinyscheme ftx scripts +script_fu_SOURCES = \ + script-fu-types.h \ + script-fu-enums.h \ + \ + script-fu.c \ + script-fu-console.c \ + script-fu-console.h \ + script-fu-eval.c \ + script-fu-eval.h \ + script-fu-interface.c \ + script-fu-interface.h \ + script-fu-text-console.h \ + script-fu-text-console.c \ + script-fu-intl.h \ + script-fu-regex.c \ + script-fu-regex.h \ + script-fu-script.c \ + script-fu-script.h \ + script-fu-scripts.c \ + script-fu-scripts.h \ + script-fu-server.c \ + script-fu-server.h \ + script-fu-utils.c \ + script-fu-utils.h \ + scheme-wrapper.c \ + scheme-wrapper.h + +LDADD = \ + $(libgimpui) \ + $(libgimpwidgets) \ + $(libgimpconfig) \ + $(libgimpmath) \ + $(libgimp) \ + $(libgimpcolor) \ + $(libgimpbase) \ + $(libtinyscheme) \ + $(libftx) \ + $(GTK_LIBS) \ + $(SOCKET_LIBS) \ + $(WINSOCK_LIBS) \ + $(RT_LIBS) \ + $(INTLLIBS) \ + $(script_fu_RC) + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/build/windows/gimprc-plug-ins.rule $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plug-ins/script-fu/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plug-ins/script-fu/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/build/windows/gimprc-plug-ins.rule $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +script-fu$(EXEEXT): $(script_fu_OBJECTS) $(script_fu_DEPENDENCIES) $(EXTRA_script_fu_DEPENDENCIES) + @rm -f script-fu$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(script_fu_OBJECTS) $(script_fu_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheme-wrapper.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-console.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-eval.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-interface.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-regex.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-script.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-scripts.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-text-console.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu-utils.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-fu.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# 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, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/scheme-wrapper.Po + -rm -f ./$(DEPDIR)/script-fu-console.Po + -rm -f ./$(DEPDIR)/script-fu-eval.Po + -rm -f ./$(DEPDIR)/script-fu-interface.Po + -rm -f ./$(DEPDIR)/script-fu-regex.Po + -rm -f ./$(DEPDIR)/script-fu-script.Po + -rm -f ./$(DEPDIR)/script-fu-scripts.Po + -rm -f ./$(DEPDIR)/script-fu-server.Po + -rm -f ./$(DEPDIR)/script-fu-text-console.Po + -rm -f ./$(DEPDIR)/script-fu-utils.Po + -rm -f ./$(DEPDIR)/script-fu.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/scheme-wrapper.Po + -rm -f ./$(DEPDIR)/script-fu-console.Po + -rm -f ./$(DEPDIR)/script-fu-eval.Po + -rm -f ./$(DEPDIR)/script-fu-interface.Po + -rm -f ./$(DEPDIR)/script-fu-regex.Po + -rm -f ./$(DEPDIR)/script-fu-script.Po + -rm -f ./$(DEPDIR)/script-fu-scripts.Po + -rm -f ./$(DEPDIR)/script-fu-server.Po + -rm -f ./$(DEPDIR)/script-fu-text-console.Po + -rm -f ./$(DEPDIR)/script-fu-utils.Po + -rm -f ./$(DEPDIR)/script-fu.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir 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-libexecPROGRAMS 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-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + + +# `windres` seems a very stupid tool and it breaks with double shlashes +# in parameter paths. Strengthen the rule a little. +@HAVE_WINDRES_TRUE@%.rc.o: +@HAVE_WINDRES_TRUE@ $(WINDRES) --define ORIGINALFILENAME_STR="$*$(EXEEXT)" \ +@HAVE_WINDRES_TRUE@ --define INTERNALNAME_STR="$*" \ +@HAVE_WINDRES_TRUE@ --define TOP_SRCDIR="`echo $(top_srcdir) | sed 's*//*/*'`" \ +@HAVE_WINDRES_TRUE@ -I"`echo $(top_srcdir)/app | sed 's%/\+%/%'`" \ +@HAVE_WINDRES_TRUE@ -I"`echo $(top_builddir)/app | sed 's%/\+%/%'`"\ +@HAVE_WINDRES_TRUE@ -I"`echo $(top_builddir) | sed 's%/\+%/%'`"\ +@HAVE_WINDRES_TRUE@ $(GIMPPLUGINRC) $@ + +# Perform static analysis on all *.scm files and look for usage of +# deprecated pdb procedures +check-for-deprecated-procedures-in-script-fu: + @echo "Looking for deprecated procedures in *.scm files" + @scm_files=`find $(top_srcdir)/plug-ins/script-fu -name "*.scm"`; \ + deprecated_procs=`$(top_builddir)/app/gimp-$(GIMP_APP_VERSION)$(EXEEXT) --dump-pdb-procedures-deprecated`; \ + for scm_file in $$scm_files; do \ + for proc in $$deprecated_procs; do \ + if grep -Eq "^([^;]*[[:blank:](])?$$proc([[:blank:])]|$$)" $$scm_file; then \ + echo "$${scm_file} uses deprecated procedure '$${proc}'"; \ + fi \ + done \ + done + +# 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. +.NOEXPORT: diff --git a/plug-ins/script-fu/ftx/LICENSE b/plug-ins/script-fu/ftx/LICENSE new file mode 100644 index 0000000..e820d87 --- /dev/null +++ b/plug-ins/script-fu/ftx/LICENSE @@ -0,0 +1,31 @@ + LICENSE TERMS + +(c) 2002 Manuel Heras-Gilsanz (manuel@heras-gilsanz.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Manuel Heras-Gilsanz nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/plug-ins/script-fu/ftx/Makefile.am b/plug-ins/script-fu/ftx/Makefile.am new file mode 100644 index 0000000..46537bf --- /dev/null +++ b/plug-ins/script-fu/ftx/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to produce Makefile.in + +AM_CFLAGS = \ + -DUSE_INTERFACE=1 \ + -I$(srcdir)/.. \ + $(GLIB_CFLAGS) + +noinst_LIBRARIES = libftx.a + +libftx_a_SOURCES = ftx.c ftx.h + +EXTRA_DIST = \ + LICENSE \ + README \ + ftx-functions.txt \ + listhome.scm diff --git a/plug-ins/script-fu/ftx/Makefile.in b/plug-ins/script-fu/ftx/Makefile.in new file mode 100644 index 0000000..e71d6ae --- /dev/null +++ b/plug-ins/script-fu/ftx/Makefile.in @@ -0,0 +1,912 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = plug-ins/script-fu/ftx +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libftx_a_AR = $(AR) $(ARFLAGS) +libftx_a_LIBADD = +am_libftx_a_OBJECTS = ftx.$(OBJEXT) +libftx_a_OBJECTS = $(am_libftx_a_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ftx.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libftx_a_SOURCES) +DIST_SOURCES = $(libftx_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = \ + -DUSE_INTERFACE=1 \ + -I$(srcdir)/.. \ + $(GLIB_CFLAGS) + +noinst_LIBRARIES = libftx.a +libftx_a_SOURCES = ftx.c ftx.h +EXTRA_DIST = \ + LICENSE \ + README \ + ftx-functions.txt \ + listhome.scm + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plug-ins/script-fu/ftx/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plug-ins/script-fu/ftx/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libftx.a: $(libftx_a_OBJECTS) $(libftx_a_DEPENDENCIES) $(EXTRA_libftx_a_DEPENDENCIES) + $(AM_V_at)-rm -f libftx.a + $(AM_V_AR)$(libftx_a_AR) libftx.a $(libftx_a_OBJECTS) $(libftx_a_LIBADD) + $(AM_V_at)$(RANLIB) libftx.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftx.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ftx.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ftx.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir 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 maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/plug-ins/script-fu/ftx/README b/plug-ins/script-fu/ftx/README new file mode 100644 index 0000000..c20b215 --- /dev/null +++ b/plug-ins/script-fu/ftx/README @@ -0,0 +1,99 @@ +TinyScheme Extensions (TSX) 1.1 [September, 2002] +(c) 2002 Manuel Heras-Gilsanz (manuel@heras-gilsanz.com) + +This software is subject to the license terms contained in the +LICENSE file. + +Changelog: +1.1 (Sept. 2002) Updated to tinyscheme 1.31 +1.0 (April 2002) First released version + + +WHAT IS TSX? + +TinyScheme Extensions is a set of dynamic libraries incorporating +additional funcionality to TinyScheme, a lightweight +implementation of the Scheme programming language. TinyScheme +(http://tinyscheme.sourceforge.net) is maintained by D. Souflis +(dsouflis@acm.org), and is based on MiniSCHEME version 0.85k4. + +Scheme is a very nice and powerful programming language, but the +basic language is very minimalistic in terms of library functions; +only basic file input / output functionality is specified. +Different implementations of the language (MIT Scheme, GUILE, +Bigloo...) provide their own extension libraries. TSX attempts to +provide commonly needed functions at a small cost in terms of +additional program footprint. The library is modularized, so that +it is possible (and easy!) to select desired functionality via +#defines in tsx.h. + + +INSTALLATION + +TSX has been tested on GNU/Linux 2.4.2 with gcc 2.96 and +libc-2.2.2, with TinyScheme 1.31. + +To install, copy the distribution file to the directory +where TinyScheme is installed (and where scheme.h lies), +and run make. If building succeeds, a file called tsx.so +should be created. This file can be loaded as a TinyScheme +extension with + + (load-extension "tsx-1.0/tsx") + +After loading TSX, you can make use of its functions. +To reduce footprint, you can choose the functionality which +will be included. To do so, have a look at tsx.h and +comment the #defines for unneeded modules. + +If you get compiler errors, make sure you have enabled +dynamic modules in your tinyscheme runtime (define USE_DL +somewhere near the top in scheme.h). + + +SAMPLE APPLICATIONS + +Three sample applications are distributed with TSX 1.0. +The code is not particularly elegant, nor written in proper +functional style, but is provided for illustration of the +implemented calls. + +-smtp.scm + Sends an email to the user getting the username from + the USER shell variable, connecting to the SMTP port + on the local machine. + +-listhome.scm + Provides a list of all the files on the user's home + directory (obtained with the HOME environment variable). + +-srepl.scm + Provides a socket-based read-eval-print-loop. It listens + for connections on the 9000 port of the local machines, + and executes the commands received. To test it, run + + telnet localhost 9000 + + after starting the sample application, and type Scheme + expressions. You will get the evaluations. To exit the + session, type "quit" and TinyScheme will exit, closing + the socket. The output of some functions will not + be the same as you would obtain on TinyScheme's + "command line", because standard output is not + redirected to the socket, but most commands work ok. + +You should copy these applications to the directory where +TinyScheme is installed (i.e., where the "scheme" binary +file resides), and can be run with: + + ./scheme listhome.scm + ./scheme smtp.scm + ./scheme srepl.scm + + +TSX FUNCTIONS + +The extension functions implemented by TinyScheme Extensions are +documented in the file "tsx-functions.txt". + +END diff --git a/plug-ins/script-fu/ftx/ftx-functions.txt b/plug-ins/script-fu/ftx/ftx-functions.txt new file mode 100644 index 0000000..5365bc5 --- /dev/null +++ b/plug-ins/script-fu/ftx/ftx-functions.txt @@ -0,0 +1,119 @@ +File and Time Extensions for TinyScheme (FTX) 1.0 [August, 2004] + +Based on the TinyScheme Extensions (TSX) 1.1 [September, 2002] +(c) 2002 Manuel Heras-Gilsanz (manuel@heras-gilsanz.com) + +This software is subject to the license terms contained in the +LICENSE file. + + +TSX FUNCTIONS + +TSX incorporates the following functions: + +*File system (included if HAVE_FILESYSTEM is defined in tsx.h) + +Scheme already defines functions to read and write files. These +functions allow access to the filesystem to check if a certain +file exists, to get its size, etc. + +In addition to these functions, a string constant DIR-SEPARATOR +has been defined. It should be used in scripts which build file +names that include one or more directories to keep the scripts +portable to different operating systems. + +(file-exists? filename) + filename: string + + This function returns #t if the indicated file exists, and + #f if it does not exist or if it is not accessible to the + requesting user. Accessibility is based on the real user + and group ID rather than the effective user ID and group ID. + +(file-type filename) + filename: string + + This function returns a value based on the file type. It + returns FILE_TYPE_FILE (1) for regular files, FILE_TYPE_DIR + (2) for directories, and FILE_TYPE_LINK (3) for symbolic + links. The value FILE_TYPE_OTHER (0) is returned if the file + is of some other type, does not exist, or if the user does + not have sufficient privileges to allow the file type to be + determined. + +(file-size filename) + filename: string + + This function returns the size (in bytes) of the + indicated file, or #f if the file does not exists or + is not accessible to the requesting user. + +(file-delete filename) + filename: string + + Removes the specified file. It returns #t if the operation + succeeds, or #f otherwise (e.g., because the file is + read-only, or because the file does not exist). + +(dir-open-stream path) + path: string + + Opens a "directory stream" on the provided directory path. + This stream will provide all the files within the directory, + using the function read-dir-entry. The stream should be closed + at the end with dir-close-stream. + +(dir-read-entry dirstream) + dirstream: directory stream, obtained with dir-open-stream. + + It returns the name of the following directory entry, or eof + if all the entries were provided. Check the return value with + with eof-object?. + +(dir-rewind dirstream) + dirstream: directory stream, obtained with dir-open-stream. + + Resets the given directory stream. The next call to dir-read-entry + will return the first entry again. It returns #t if the operation + succeeds, or #f otherwise (ie. dirstream not valid).. + +(dir-close-stream dirstream) + dirstream: directory stream, obtained with dir-open-stream. + + Close directory stream. No further calls to read-dir-entry should + be performed. + +(dir-make dirname . mode) + dirname: string + mode: integer representing permissions + + Create the directory specified, setting the directory permissions based + upon the optional mode argument (taking into account the current + umask). If no mode is specified then use the default (umask) + permissions. Returns #t if the operation succeeds, otherwise #f. + Possible reasons for failure are that the directory already exists, + the user is not authorized to create it, or the mode is incorrectly + specified). + +*Time (available if HAVE_TIME is defined in tsx.h) + +(time) + Returns the current local time, as a list of integer + containing: + (year month day-of-month hour min sec millisec) + The year is expressed as an offset from 1900. + +(gettimeofday) + Returns a list containing the number of seconds from + the beginning of the day, and microseconds within the + current second. + +(usleep microsec) + microsec: integer + + Suspends execution of the calling thread during the + specified number of microseconds. + + +END + diff --git a/plug-ins/script-fu/ftx/ftx.c b/plug-ins/script-fu/ftx/ftx.c new file mode 100644 index 0000000..f9de1bf --- /dev/null +++ b/plug-ins/script-fu/ftx/ftx.c @@ -0,0 +1,415 @@ +/* TinyScheme Extensions + * (c) 2002 Visual Tools, S.A. + * Manuel Heras-Gilsanz (manuel@heras-gilsanz.com) + * + * This software is subject to the terms stated in the + * LICENSE file. + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <time.h> + +#include <glib.h> + +#include "tinyscheme/scheme-private.h" + +#undef cons + +typedef enum +{ + FILE_TYPE_UNKNOWN = 0, FILE_TYPE_FILE, FILE_TYPE_DIR, FILE_TYPE_LINK +} FileType; + +struct +named_constant { + const char *name; + FileType value; +}; + +struct named_constant +file_type_constants[] = { + { "FILE-TYPE-UNKNOWN", FILE_TYPE_UNKNOWN }, + { "FILE-TYPE-FILE", FILE_TYPE_FILE }, + { "FILE-TYPE-DIR", FILE_TYPE_DIR }, + { "FILE-TYPE-LINK", FILE_TYPE_LINK }, + { NULL, 0 } +}; + +pointer foreign_fileexists(scheme *sc, pointer args); +pointer foreign_filetype(scheme *sc, pointer args); +pointer foreign_filesize(scheme *sc, pointer args); +pointer foreign_filedelete(scheme *sc, pointer args); +pointer foreign_diropenstream(scheme *sc, pointer args); +pointer foreign_dirreadentry(scheme *sc, pointer args); +pointer foreign_dirrewind(scheme *sc, pointer args); +pointer foreign_dirclosestream(scheme *sc, pointer args); +pointer foreign_mkdir(scheme *sc, pointer args); + +pointer foreign_getenv(scheme *sc, pointer args); +pointer foreign_time(scheme *sc, pointer args); +pointer foreign_gettimeofday(scheme *sc, pointer args); +pointer foreign_usleep(scheme *sc, pointer args); +void init_ftx (scheme *sc); + + +pointer foreign_fileexists(scheme *sc, pointer args) +{ + pointer first_arg; + char *filename; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_string(first_arg)) + return sc->F; + + filename = sc->vptr->string_value(first_arg); + filename = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + return sc->T; + + return sc->F; +} + +pointer foreign_filetype(scheme *sc, pointer args) +{ + pointer first_arg; + char *filename; + int retcode; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_string(first_arg)) + return sc->F; + + filename = sc->vptr->string_value(first_arg); + filename = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL); + + if (g_file_test(filename, G_FILE_TEST_IS_SYMLINK)) + retcode = FILE_TYPE_LINK; + else if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + retcode = FILE_TYPE_FILE; + else if (g_file_test(filename, G_FILE_TEST_IS_DIR)) + retcode = FILE_TYPE_DIR; + else + retcode = FILE_TYPE_UNKNOWN; + + return sc->vptr->mk_integer(sc, retcode); +} + +pointer foreign_filesize(scheme *sc, pointer args) +{ + pointer first_arg; + pointer ret; + struct stat buf; + char * filename; + int retcode; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_string(first_arg)) + return sc->F; + + filename = sc->vptr->string_value(first_arg); + filename = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL); + retcode = stat(filename, &buf); + if (retcode == 0) + ret = sc->vptr->mk_integer(sc,buf.st_size); + else + ret = sc->F; + return ret; +} + +pointer foreign_filedelete(scheme *sc, pointer args) +{ + pointer first_arg; + pointer ret; + char * filename; + int retcode; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_string(first_arg)) { + return sc->F; + } + + filename = sc->vptr->string_value(first_arg); + filename = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL); + retcode = unlink(filename); + if (retcode == 0) + ret = sc->T; + else + ret = sc->F; + return ret; +} + +pointer foreign_diropenstream(scheme *sc, pointer args) +{ + pointer first_arg; + char *dirpath; + GDir *dir; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_string(first_arg)) + return sc->F; + + dirpath = sc->vptr->string_value(first_arg); + dirpath = g_filename_from_utf8 (dirpath, -1, NULL, NULL, NULL); + + dir = g_dir_open(dirpath, 0, NULL); + if (dir == NULL) + return sc->F; + + /* Stuffing a pointer in a long may not always be portable ~~~~~ */ + return (sc->vptr->mk_integer(sc, (long) dir)); +} + +pointer foreign_dirreadentry(scheme *sc, pointer args) +{ + pointer first_arg; + GDir *dir; + gchar *entry; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_integer(first_arg)) + return sc->F; + + dir = (GDir *) sc->vptr->ivalue(first_arg); + if (dir == NULL) + return sc->F; + + entry = (gchar *)g_dir_read_name(dir); + if (entry == NULL) + return sc->EOF_OBJ; + + entry = g_filename_to_utf8 (entry, -1, NULL, NULL, NULL); + return (sc->vptr->mk_string(sc, entry)); +} + +pointer foreign_dirrewind(scheme *sc, pointer args) +{ + pointer first_arg; + GDir *dir; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_integer(first_arg)) + return sc->F; + + dir = (GDir *) sc->vptr->ivalue(first_arg); + if (dir == NULL) + return sc->F; + + g_dir_rewind(dir); + return sc->T; +} + +pointer foreign_dirclosestream(scheme *sc, pointer args) +{ + pointer first_arg; + GDir *dir; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_integer(first_arg)) + return sc->F; + + dir = (GDir *) sc->vptr->ivalue(first_arg); + if (dir == NULL) + return sc->F; + + g_dir_close(dir); + return sc->T; +} + +pointer foreign_mkdir(scheme *sc, pointer args) +{ + pointer first_arg; + pointer rest; + pointer second_arg; + char *dirname; + mode_t mode; + int retcode; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_string(first_arg)) + return sc->F; + dirname = sc->vptr->string_value(first_arg); + dirname = g_filename_from_utf8 (dirname, -1, NULL, NULL, NULL); + + rest = sc->vptr->pair_cdr(args); + if (sc->vptr->is_pair(rest)) /* optional mode argument */ + { + second_arg = sc->vptr->pair_car(rest); + if (!sc->vptr->is_integer(second_arg)) + return sc->F; + mode = sc->vptr->ivalue(second_arg); + } + else + mode = 0777; + + retcode = g_mkdir(dirname, (mode_t)mode); + if (retcode == 0) + return sc->T; + else + return sc->F; +} + +pointer foreign_getenv(scheme *sc, pointer args) +{ + pointer first_arg; + pointer ret; + char *varname; + const char *value; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + + if (!sc->vptr->is_string(first_arg)) + return sc->F; + + varname = sc->vptr->string_value(first_arg); + value = g_getenv(varname); + if (value == NULL) + ret = sc->F; + else + ret = sc->vptr->mk_string(sc,value); + + return ret; +} + +pointer foreign_time(scheme *sc, pointer args) +{ + time_t now; + struct tm *now_tm; + pointer ret; + + if (args != sc->NIL) + return sc->F; + + time(&now); + now_tm = localtime(&now); + + ret = sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) now_tm->tm_year), + sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) now_tm->tm_mon), + sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) now_tm->tm_mday), + sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) now_tm->tm_hour), + sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) now_tm->tm_min), + sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) now_tm->tm_sec),sc->NIL)))))); + + return ret; +} + +pointer foreign_gettimeofday(scheme *sc, pointer args) +{ + pointer ret; + gint64 time; + + time = g_get_real_time (); + + ret = sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) time / G_USEC_PER_SEC), + sc->vptr->cons(sc, sc->vptr->mk_integer(sc,(long) time % G_USEC_PER_SEC), + sc->NIL)); + + return ret; +} + +pointer foreign_usleep(scheme *sc, pointer args) +{ + pointer first_arg; + long usec; + + if (args == sc->NIL) + return sc->F; + + first_arg = sc->vptr->pair_car(args); + if (!sc->vptr->is_integer(first_arg)) + return sc->F; + + usec = sc->vptr->ivalue(first_arg); + g_usleep(usec); + + return sc->T; +} + +/* This function gets called when TinyScheme is loading the extension */ +void init_ftx (scheme *sc) +{ + int i; + + sc->vptr->scheme_define(sc,sc->global_env, + sc->vptr->mk_symbol(sc,"getenv"), + sc->vptr->mk_foreign_func(sc, foreign_getenv)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"time"), + sc->vptr->mk_foreign_func(sc, foreign_time)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"gettimeofday"), + sc->vptr->mk_foreign_func(sc, foreign_gettimeofday)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"usleep"), + sc->vptr->mk_foreign_func(sc, foreign_usleep)); + + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"file-exists?"), + sc->vptr->mk_foreign_func(sc, foreign_fileexists)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"file-type"), + sc->vptr->mk_foreign_func(sc, foreign_filetype)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"file-size"), + sc->vptr->mk_foreign_func(sc, foreign_filesize)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"file-delete"), + sc->vptr->mk_foreign_func(sc, foreign_filedelete)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"dir-open-stream"), + sc->vptr->mk_foreign_func(sc, foreign_diropenstream)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"dir-read-entry"), + sc->vptr->mk_foreign_func(sc, foreign_dirreadentry)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"dir-rewind"), + sc->vptr->mk_foreign_func(sc, foreign_dirrewind)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"dir-close-stream"), + sc->vptr->mk_foreign_func(sc, foreign_dirclosestream)); + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc,"dir-make"), + sc->vptr->mk_foreign_func(sc, foreign_mkdir)); + + for (i = 0; file_type_constants[i].name != NULL; ++i) + { + sc->vptr->scheme_define(sc, sc->global_env, + sc->vptr->mk_symbol(sc, file_type_constants[i].name), + sc->vptr->mk_integer(sc, file_type_constants[i].value)); + } +} diff --git a/plug-ins/script-fu/ftx/ftx.h b/plug-ins/script-fu/ftx/ftx.h new file mode 100644 index 0000000..f40c30d --- /dev/null +++ b/plug-ins/script-fu/ftx/ftx.h @@ -0,0 +1,2 @@ +/* This function gets called when TinyScheme is initializing the extension */ +void init_ftx (scheme *sc); diff --git a/plug-ins/script-fu/ftx/listhome.scm b/plug-ins/script-fu/ftx/listhome.scm new file mode 100644 index 0000000..1fa8d14 --- /dev/null +++ b/plug-ins/script-fu/ftx/listhome.scm @@ -0,0 +1,58 @@ +; listhome.scm +; Sample usage of TinyScheme Extension +; This simple program lists the directory entries on the +; user's home directory. + +; It uses the following TinyScheme Extension functions: +; getenv +; Used to get HOME environment variable. +; open-dir-stream +; Used to open directory stream. +; read-dir-entry +; Used to read directory entries. +; close-dir-entry +; Used at the end, to close directory stream when done. + +; check that extensions are enabled +(if (not (defined? 'load-extension)) + (begin + (display "TinyScheme has extensions disabled. Enable them!!") + (newline) + (quit))) + +; load TinyScheme extension +(load-extension "tsx-1.1/tsx") + +; check that the necessary functions are available (the user +; might have removed some functionality...) +(if (or + (not (defined? 'getenv)) + (not (defined? 'dir-open-stream)) + (not (defined? 'dir-read-entry)) + (not (defined? 'dir-close-stream))) + (begin + (display "Some necessary functions are not available. Exiting!") + (newline) + (quit))) + +; get user's home dir from HOME environment var +(define homedir (getenv "HOME")) +(display "Listing contents of ") (display homedir) (newline) + +; create directory stream to read dir entries +(define dirstream (dir-open-stream homedir)) +(if (not dirstream) + (begin + (display "Unable to open home directory!! Check value of HOME environment var.") + (quit))) + +(let listentry ((entry (dir-read-entry dirstream))) + (if (eof-object? entry) + #t + (begin + (display entry) + (newline) + (listentry (dir-read-entry dirstream))))) + +(dir-close-stream dirstream) + diff --git a/plug-ins/script-fu/scheme-wrapper.c b/plug-ins/script-fu/scheme-wrapper.c new file mode 100644 index 0000000..69e22c0 --- /dev/null +++ b/plug-ins/script-fu/scheme-wrapper.c @@ -0,0 +1,1671 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#if 0 +#define DEBUG_MARSHALL 0 /* No need to define this until you need it */ +#define DEBUG_SCRIPTS 0 +#endif + +#include "config.h" + +#include <string.h> + +#include <glib/gstdio.h> + +#include <gtk/gtk.h> + +#include "libgimp/gimp.h" + +#include "tinyscheme/scheme-private.h" +#if USE_DL +#include "tinyscheme/dynload.h" +#endif +#include "ftx/ftx.h" + +#include "script-fu-types.h" + +#include "script-fu-console.h" +#include "script-fu-interface.h" +#include "script-fu-regex.h" +#include "script-fu-scripts.h" +#include "script-fu-server.h" + +#include "scheme-wrapper.h" + + +#undef cons + +static void ts_init_constants (scheme *sc); +static void ts_init_enum (scheme *sc, + GType enum_type); +static void ts_init_procedures (scheme *sc, + gboolean register_scipts); +static void convert_string (gchar *str); +static pointer script_fu_marshal_procedure_call (scheme *sc, + pointer a, + gboolean permissive); +static pointer script_fu_marshal_procedure_call_strict (scheme *sc, + pointer a); +static pointer script_fu_marshal_procedure_call_permissive (scheme *sc, + pointer a); +static void script_fu_marshal_destroy_args (GimpParam *params, + gint n_params); + +static pointer script_fu_register_call (scheme *sc, + pointer a); +static pointer script_fu_menu_register_call (scheme *sc, + pointer a); +static pointer script_fu_quit_call (scheme *sc, + pointer a); +static pointer script_fu_nil_call (scheme *sc, + pointer a); + +static gboolean ts_load_file (const gchar *dirname, + const gchar *basename); + +typedef struct +{ + const gchar *name; + gint value; +} NamedConstant; + +static const NamedConstant script_constants[] = +{ + /* Useful values from libgimpbase/gimplimits.h */ + { "MIN-IMAGE-SIZE", GIMP_MIN_IMAGE_SIZE }, + { "MAX-IMAGE-SIZE", GIMP_MAX_IMAGE_SIZE }, + { "MIN-RESOLUTION", GIMP_MIN_RESOLUTION }, + { "MAX-RESOLUTION", GIMP_MAX_RESOLUTION }, + + /* Useful misc stuff */ + { "TRUE", TRUE }, + { "FALSE", FALSE }, + + /* Builtin units */ + { "UNIT-PIXEL", GIMP_UNIT_PIXEL }, + { "UNIT-INCH", GIMP_UNIT_INCH }, + { "UNIT-MM", GIMP_UNIT_MM }, + { "UNIT-POINT", GIMP_UNIT_POINT }, + { "UNIT-PICA", GIMP_UNIT_PICA }, + + /* Script-Fu types */ + { "SF-IMAGE", SF_IMAGE }, + { "SF-DRAWABLE", SF_DRAWABLE }, + { "SF-LAYER", SF_LAYER }, + { "SF-CHANNEL", SF_CHANNEL }, + { "SF-VECTORS", SF_VECTORS }, + { "SF-COLOR", SF_COLOR }, + { "SF-TOGGLE", SF_TOGGLE }, + { "SF-VALUE", SF_VALUE }, + { "SF-STRING", SF_STRING }, + { "SF-FILENAME", SF_FILENAME }, + { "SF-DIRNAME", SF_DIRNAME }, + { "SF-ADJUSTMENT", SF_ADJUSTMENT }, + { "SF-FONT", SF_FONT }, + { "SF-PATTERN", SF_PATTERN }, + { "SF-BRUSH", SF_BRUSH }, + { "SF-GRADIENT", SF_GRADIENT }, + { "SF-OPTION", SF_OPTION }, + { "SF-PALETTE", SF_PALETTE }, + { "SF-TEXT", SF_TEXT }, + { "SF-ENUM", SF_ENUM }, + { "SF-DISPLAY", SF_DISPLAY }, + + /* For SF-ADJUSTMENT */ + { "SF-SLIDER", SF_SLIDER }, + { "SF-SPINNER", SF_SPINNER }, + + { NULL, 0 } +}; + + +static scheme sc; + + +void +tinyscheme_init (GList *path, + gboolean register_scripts) +{ + /* init the interpreter */ + if (! scheme_init (&sc)) + { + g_message ("Could not initialize TinyScheme!"); + return; + } + + scheme_set_input_port_file (&sc, stdin); + scheme_set_output_port_file (&sc, stdout); + ts_register_output_func (ts_stdout_output_func, NULL); + + /* Initialize the TinyScheme extensions */ + init_ftx (&sc); + script_fu_regex_init (&sc); + + /* register in the interpreter the gimp functions and types. */ + ts_init_constants (&sc); + ts_init_procedures (&sc, register_scripts); + + if (path) + { + GList *list; + + for (list = path; list; list = g_list_next (list)) + { + gchar *dir = g_file_get_path (list->data); + + if (ts_load_file (dir, "script-fu.init")) + { + /* To improve compatibility with older Script-Fu scripts, + * load script-fu-compat.init from the same directory. + */ + ts_load_file (dir, "script-fu-compat.init"); + + /* To improve compatibility with older GIMP version, + * load plug-in-compat.init from the same directory. + */ + ts_load_file (dir, "plug-in-compat.init"); + + g_free (dir); + + break; + } + + g_free (dir); + } + + if (list == NULL) + g_printerr ("Unable to read initialization file script-fu.init\n"); + } +} + +/* Create an SF-RUN-MODE constant for use in scripts. + * It is set to the run mode state determined by GIMP. + */ +void +ts_set_run_mode (GimpRunMode run_mode) +{ + pointer symbol; + + symbol = sc.vptr->mk_symbol (&sc, "SF-RUN-MODE"); + sc.vptr->scheme_define (&sc, sc.global_env, symbol, + sc.vptr->mk_integer (&sc, run_mode)); + sc.vptr->setimmutable (symbol); +} + +void +ts_set_print_flag (gint print_flag) +{ + sc.print_output = print_flag; +} + +void +ts_print_welcome (void) +{ + ts_output_string (TS_OUTPUT_NORMAL, + "Welcome to TinyScheme, Version 1.40\n", -1); + ts_output_string (TS_OUTPUT_NORMAL, + "Copyright (c) Dimitrios Souflis\n", -1); +} + +void +ts_interpret_stdin (void) +{ + scheme_load_file (&sc, stdin); +} + +gint +ts_interpret_string (const gchar *expr) +{ +#if DEBUG_SCRIPTS + sc.print_output = 1; + sc.tracing = 1; +#endif + + sc.vptr->load_string (&sc, (char *) expr); + + return sc.retcode; +} + +const gchar * +ts_get_success_msg (void) +{ + if (sc.vptr->is_string (sc.value)) + return sc.vptr->string_value (sc.value); + + return "Success"; +} + +void +ts_stdout_output_func (TsOutputType type, + const char *string, + int len, + gpointer user_data) +{ + if (len < 0) + len = strlen (string); + fprintf (stdout, "%.*s", len, string); + fflush (stdout); +} + +void +ts_gstring_output_func (TsOutputType type, + const char *string, + int len, + gpointer user_data) +{ + GString *gstr = (GString *) user_data; + + g_string_append_len (gstr, string, len); +} + + +/* private functions */ + +/* + * Below can be found the functions responsible for registering the + * gimp functions and types against the scheme interpreter. + */ +static void +ts_init_constants (scheme *sc) +{ + const gchar **enum_type_names; + gint n_enum_type_names; + gint i; + pointer symbol; + GQuark quark; + + symbol = sc->vptr->mk_symbol (sc, "gimp-directory"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_directory ())); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "gimp-data-directory"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_data_directory ())); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "gimp-plug-in-directory"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_plug_in_directory ())); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "gimp-locale-directory"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_locale_directory ())); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "gimp-sysconf-directory"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_sysconf_directory ())); + sc->vptr->setimmutable (symbol); + + enum_type_names = gimp_enums_get_type_names (&n_enum_type_names); + quark = g_quark_from_static_string ("gimp-compat-enum"); + + for (i = 0; i < n_enum_type_names; i++) + { + const gchar *enum_name = enum_type_names[i]; + GType enum_type = g_type_from_name (enum_name); + + ts_init_enum (sc, enum_type); + + enum_type = (GType) g_type_get_qdata (enum_type, quark); + + if (enum_type) + ts_init_enum (sc, enum_type); + } + + /* Constants used in the register block of scripts */ + for (i = 0; script_constants[i].name != NULL; ++i) + { + symbol = sc->vptr->mk_symbol (sc, script_constants[i].name); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_integer (sc, + script_constants[i].value)); + sc->vptr->setimmutable (symbol); + } + + /* Define string constant for use in building paths to files/directories */ + symbol = sc->vptr->mk_symbol (sc, "DIR-SEPARATOR"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, G_DIR_SEPARATOR_S)); + sc->vptr->setimmutable (symbol); + + /* Define string constant for use in building search paths */ + symbol = sc->vptr->mk_symbol (sc, "SEARCHPATH-SEPARATOR"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, G_SEARCHPATH_SEPARATOR_S)); + sc->vptr->setimmutable (symbol); + + /* These constants are deprecated and will be removed at a later date. */ + symbol = sc->vptr->mk_symbol (sc, "gimp-dir"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_directory ())); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "gimp-data-dir"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_data_directory ())); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "gimp-plugin-dir"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_string (sc, gimp_plug_in_directory ())); + sc->vptr->setimmutable (symbol); +} + +static void +ts_init_enum (scheme *sc, + GType enum_type) +{ + GEnumClass *enum_class = g_type_class_ref (enum_type); + GEnumValue *value; + + for (value = enum_class->values; value->value_name; value++) + { + if (g_str_has_prefix (value->value_name, "GIMP_")) + { + gchar *scheme_name; + pointer symbol; + + scheme_name = g_strdup (value->value_name + strlen ("GIMP_")); + convert_string (scheme_name); + + symbol = sc->vptr->mk_symbol (sc, scheme_name); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_integer (sc, value->value)); + sc->vptr->setimmutable (symbol); + + g_free (scheme_name); + } + } + + g_type_class_unref (enum_class); +} + +static void +ts_init_procedures (scheme *sc, + gboolean register_scripts) +{ + gchar **proc_list; + gint num_procs; + gint i; + pointer symbol; + +#if USE_DL + symbol = sc->vptr->mk_symbol (sc,"load-extension"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_foreign_func (sc, scm_load_ext)); + sc->vptr->setimmutable (symbol); +#endif + + symbol = sc->vptr->mk_symbol (sc, "script-fu-register"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_foreign_func (sc, + register_scripts ? + script_fu_register_call : + script_fu_nil_call)); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "script-fu-menu-register"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_foreign_func (sc, + register_scripts ? + script_fu_menu_register_call : + script_fu_nil_call)); + sc->vptr->setimmutable (symbol); + + symbol = sc->vptr->mk_symbol (sc, "script-fu-quit"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_foreign_func (sc, script_fu_quit_call)); + sc->vptr->setimmutable (symbol); + + /* register the database execution procedure */ + symbol = sc->vptr->mk_symbol (sc, "gimp-proc-db-call"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_foreign_func (sc, + script_fu_marshal_procedure_call_strict)); + sc->vptr->setimmutable (symbol); + + /* register the internal database execution procedure; see comment below */ + symbol = sc->vptr->mk_symbol (sc, "-gimp-proc-db-call"); + sc->vptr->scheme_define (sc, sc->global_env, symbol, + sc->vptr->mk_foreign_func (sc, + script_fu_marshal_procedure_call_permissive)); + sc->vptr->setimmutable (symbol); + + gimp_procedural_db_query (".*", ".*", ".*", ".*", ".*", ".*", ".*", + &num_procs, &proc_list); + + /* Register each procedure as a scheme func */ + for (i = 0; i < num_procs; i++) + { + gchar *buff; + + /* Build a define that will call the foreign function. + * The Scheme statement was suggested by Simon Budig. + * + * We call the procedure through -gimp-proc-db-call, which is a more + * permissive version of gimp-proc-db-call, that accepts (and ignores) + * any number of arguments for nullary procedures, for backward + * compatibility. + */ + buff = g_strdup_printf (" (define (%s . args)" + " (apply -gimp-proc-db-call \"%s\" args))", + proc_list[i], proc_list[i]); + + /* Execute the 'define' */ + sc->vptr->load_string (sc, buff); + + g_free (buff); + } + + g_strfreev (proc_list); +} + +static gboolean +ts_load_file (const gchar *dirname, + const gchar *basename) +{ + gchar *filename; + FILE *fin; + + filename = g_build_filename (dirname, basename, NULL); + + fin = g_fopen (filename, "rb"); + + g_free (filename); + + if (fin) + { + scheme_load_file (&sc, fin); + fclose (fin); + + return TRUE; + } + + return FALSE; +} + +static void +convert_string (gchar *str) +{ + while (*str) + { + if (*str == '_') *str = '-'; + str++; + } +} + +/* This is called by the Scheme interpreter to allow calls to GIMP functions */ +static pointer +script_fu_marshal_procedure_call (scheme *sc, + pointer a, + gboolean permissive) +{ + GimpParam *args; + GimpParam *values = NULL; + gint nvalues; + gchar *proc_name; + gchar *proc_blurb; + gchar *proc_help; + gchar *proc_author; + gchar *proc_copyright; + gchar *proc_date; + GimpPDBProcType proc_type; + gint nparams; + gint nreturn_vals; + GimpParamDef *params; + GimpParamDef *return_vals; + gchar error_str[1024]; + gint i; + gint success = TRUE; + pointer return_val = sc->NIL; + +#if DEBUG_MARSHALL +/* These three #defines are from Tinyscheme (tinyscheme/scheme.c) */ +#define T_MASKTYPE 31 +#define typeflag(p) ((p)->_flag) +#define type(p) (typeflag(p)&T_MASKTYPE) + + static const char *ts_types[] = + { + "T_NONE", + "T_STRING", "T_NUMBER", "T_SYMBOL", "T_PROC", + "T_PAIR", "T_CLOSURE", "T_CONTINUATION", "T_FOREIGN", + "T_CHARACTER", "T_PORT", "T_VECTOR", "T_MACRO", + "T_PROMISE", "T_ENVIRONMENT","T_ARRAY" + }; + + g_printerr ("\nIn %s()\n", G_STRFUNC); +#endif + + /* Make sure there are arguments */ + if (a == sc->NIL) + return foreign_error (sc, + "Procedure argument marshaller was called with no arguments. " + "The procedure to be executed and the arguments it requires " + "(possibly none) must be specified.", 0); + + /* The PDB procedure name is the argument or first argument of the list */ + if (sc->vptr->is_pair (a)) + proc_name = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + else + proc_name = g_strdup (sc->vptr->string_value (a)); + +#ifdef DEBUG_MARSHALL + g_printerr (" proc name: %s\n", proc_name); + g_printerr (" parms rcvd: %d\n", sc->vptr->list_length (sc, a)-1); +#endif + + /* report the current command */ + script_fu_interface_report_cc (proc_name); + + /* Attempt to fetch the procedure from the database */ + if (! gimp_procedural_db_proc_info (proc_name, + &proc_blurb, + &proc_help, + &proc_author, + &proc_copyright, + &proc_date, + &proc_type, + &nparams, &nreturn_vals, + ¶ms, &return_vals)) + { +#ifdef DEBUG_MARSHALL + g_printerr (" Invalid procedure name\n"); +#endif + g_snprintf (error_str, sizeof (error_str), + "Invalid procedure name %s specified", proc_name); + return foreign_error (sc, error_str, 0); + } + + /* Free the name and the description which are of no use here. */ + for (i = 0; i < nparams; i++) + { + g_free (params[i].name); + g_free (params[i].description); + } + for (i = 0; i < nreturn_vals; i++) + { + g_free (return_vals[i].name); + g_free (return_vals[i].description); + } + + /* Check the supplied number of arguments */ + if ((nparams > 0 || ! permissive) && + (sc->vptr->list_length (sc, a) - 1) != nparams) + { +#if DEBUG_MARSHALL + g_printerr (" Invalid number of arguments (expected %d but received %d)", + nparams, (sc->vptr->list_length (sc, a) - 1)); +#endif + g_snprintf (error_str, sizeof (error_str), + "Invalid number of arguments for %s (expected %d but received %d)", + proc_name, nparams, (sc->vptr->list_length (sc, a) - 1)); + return foreign_error (sc, error_str, 0); + } + + /* Marshall the supplied arguments */ + if (nparams) + args = g_new (GimpParam, nparams); + else + args = NULL; + + for (i = 0; i < nparams; i++) + { + gint32 n_elements; + pointer vector; + gint j; + + a = sc->vptr->pair_cdr (a); + +#if DEBUG_MARSHALL + { + const gchar *type_name; + + gimp_enum_get_value (GIMP_TYPE_PDB_ARG_TYPE, + params[i].type, + &type_name, NULL, NULL, NULL); + + g_printerr (" param %d - expecting type %s (%d)\n", + i + 1, type_name, params[i].type); + g_printerr (" passed arg is type %s (%d)\n", + ts_types[ type(sc->vptr->pair_car (a)) ], + type(sc->vptr->pair_car (a))); + } +#endif + + args[i].type = params[i].type; + + switch (params[i].type) + { + case GIMP_PDB_INT32: + case GIMP_PDB_DISPLAY: + case GIMP_PDB_IMAGE: + case GIMP_PDB_ITEM: + case GIMP_PDB_LAYER: + case GIMP_PDB_CHANNEL: + case GIMP_PDB_DRAWABLE: + case GIMP_PDB_SELECTION: + case GIMP_PDB_VECTORS: + if (!sc->vptr->is_number (sc->vptr->pair_car (a))) + success = FALSE; + if (success) + { + args[i].data.d_int32 = sc->vptr->ivalue (sc->vptr->pair_car (a)); +#if DEBUG_MARSHALL + g_printerr (" int32 arg is '%d'\n", args[i].data.d_int32); +#endif + } + break; + + case GIMP_PDB_INT16: + if (!sc->vptr->is_number (sc->vptr->pair_car (a))) + success = FALSE; + if (success) + { + args[i].data.d_int16 = (gint16) sc->vptr->ivalue (sc->vptr->pair_car (a)); +#if DEBUG_MARSHALL + g_printerr (" int16 arg is '%d'\n", args[i].data.d_int16); +#endif + } + break; + + case GIMP_PDB_INT8: + if (!sc->vptr->is_number (sc->vptr->pair_car (a))) + success = FALSE; + if (success) + { + args[i].data.d_int8 = (guint8) sc->vptr->ivalue (sc->vptr->pair_car (a)); +#if DEBUG_MARSHALL + g_printerr (" int8 arg is '%u'\n", args[i].data.d_int8); +#endif + } + break; + + case GIMP_PDB_FLOAT: + if (!sc->vptr->is_number (sc->vptr->pair_car (a))) + success = FALSE; + if (success) + { + args[i].data.d_float = sc->vptr->rvalue (sc->vptr->pair_car (a)); +#if DEBUG_MARSHALL + g_printerr (" float arg is '%f'\n", args[i].data.d_float); +#endif + } + break; + + case GIMP_PDB_STRING: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + success = FALSE; + if (success) + { + args[i].data.d_string = sc->vptr->string_value (sc->vptr->pair_car (a)); +#if DEBUG_MARSHALL + g_printerr (" string arg is '%s'\n", args[i].data.d_string); +#endif + } + break; + + case GIMP_PDB_INT32ARRAY: + vector = sc->vptr->pair_car (a); + if (!sc->vptr->is_vector (vector)) + success = FALSE; + if (success) + { + n_elements = args[i-1].data.d_int32; + if (n_elements < 0 || + n_elements > sc->vptr->vector_length (vector)) + { + g_snprintf (error_str, sizeof (error_str), + "INT32 vector (argument %d) for function %s has " + "size of %ld but expected size of %d", + i+1, proc_name, + sc->vptr->vector_length (vector), n_elements); + return foreign_error (sc, error_str, 0); + } + + args[i].data.d_int32array = g_new (gint32, n_elements); + + for (j = 0; j < n_elements; j++) + { + pointer v_element = sc->vptr->vector_elem (vector, j); + + /* FIXME: Check values in vector stay within range for each type. */ + if (!sc->vptr->is_number (v_element)) + { + g_snprintf (error_str, sizeof (error_str), + "Item %d in vector is not a number (argument %d for function %s)", + j+1, i+1, proc_name); + return foreign_error (sc, error_str, vector); + } + + args[i].data.d_int32array[j] = + (gint32) sc->vptr->ivalue (v_element); + } + +#if DEBUG_MARSHALL + { + glong count = sc->vptr->vector_length (vector); + g_printerr (" int32 vector has %ld elements\n", count); + if (count > 0) + { + g_printerr (" "); + for (j = 0; j < count; ++j) + g_printerr (" %ld", + sc->vptr->ivalue ( sc->vptr->vector_elem (vector, j) )); + g_printerr ("\n"); + } + } +#endif + } + break; + + case GIMP_PDB_INT16ARRAY: + vector = sc->vptr->pair_car (a); + if (!sc->vptr->is_vector (vector)) + success = FALSE; + if (success) + { + n_elements = args[i-1].data.d_int32; + if (n_elements < 0 || n_elements > sc->vptr->vector_length (vector)) + { + g_snprintf (error_str, sizeof (error_str), + "INT16 vector (argument %d) for function %s has " + "size of %ld but expected size of %d", + i+1, proc_name, sc->vptr->vector_length (vector), n_elements); + return foreign_error (sc, error_str, 0); + } + + args[i].data.d_int16array = g_new (gint16, n_elements); + + for (j = 0; j < n_elements; j++) + { + pointer v_element = sc->vptr->vector_elem (vector, j); + + if (!sc->vptr->is_number (v_element)) + { + g_snprintf (error_str, sizeof (error_str), + "Item %d in vector is not a number (argument %d for function %s)", + j+1, i+1, proc_name); + return foreign_error (sc, error_str, vector); + } + + args[i].data.d_int16array[j] = + (gint16) sc->vptr->ivalue (v_element); + } + +#if DEBUG_MARSHALL + { + glong count = sc->vptr->vector_length (vector); + g_printerr (" int16 vector has %ld elements\n", count); + if (count > 0) + { + g_printerr (" "); + for (j = 0; j < count; ++j) + g_printerr (" %ld", + sc->vptr->ivalue ( sc->vptr->vector_elem (vector, j) )); + g_printerr ("\n"); + } + } +#endif + } + break; + + case GIMP_PDB_INT8ARRAY: + vector = sc->vptr->pair_car (a); + if (!sc->vptr->is_vector (vector)) + success = FALSE; + if (success) + { + n_elements = args[i-1].data.d_int32; + if (n_elements < 0 || + n_elements > sc->vptr->vector_length (vector)) + { + g_snprintf (error_str, sizeof (error_str), + "INT8 vector (argument %d) for function %s has " + "size of %ld but expected size of %d", + i+1, proc_name, + sc->vptr->vector_length (vector), n_elements); + return foreign_error (sc, error_str, 0); + } + + args[i].data.d_int8array = g_new (guint8, n_elements); + + for (j = 0; j < n_elements; j++) + { + pointer v_element = sc->vptr->vector_elem (vector, j); + + if (!sc->vptr->is_number (v_element)) + { + g_snprintf (error_str, sizeof (error_str), + "Item %d in vector is not a number (argument %d for function %s)", + j+1, i+1, proc_name); + return foreign_error (sc, error_str, vector); + } + + args[i].data.d_int8array[j] = + (guint8) sc->vptr->ivalue (v_element); + } + +#if DEBUG_MARSHALL + { + glong count = sc->vptr->vector_length (vector); + g_printerr (" int8 vector has %ld elements\n", count); + if (count > 0) + { + g_printerr (" "); + for (j = 0; j < count; ++j) + g_printerr (" %ld", + sc->vptr->ivalue ( sc->vptr->vector_elem (vector, j) )); + g_printerr ("\n"); + } + } +#endif + } + break; + + case GIMP_PDB_FLOATARRAY: + vector = sc->vptr->pair_car (a); + if (!sc->vptr->is_vector (vector)) + success = FALSE; + if (success) + { + n_elements = args[i-1].data.d_int32; + if (n_elements < 0 || + n_elements > sc->vptr->vector_length (vector)) + { + g_snprintf (error_str, sizeof (error_str), + "FLOAT vector (argument %d) for function %s has " + "size of %ld but expected size of %d", + i+1, proc_name, + sc->vptr->vector_length (vector), n_elements); + return foreign_error (sc, error_str, 0); + } + + args[i].data.d_floatarray = g_new (gdouble, n_elements); + + for (j = 0; j < n_elements; j++) + { + pointer v_element = sc->vptr->vector_elem (vector, j); + + if (!sc->vptr->is_number (v_element)) + { + g_snprintf (error_str, sizeof (error_str), + "Item %d in vector is not a number (argument %d for function %s)", + j+1, i+1, proc_name); + return foreign_error (sc, error_str, vector); + } + + args[i].data.d_floatarray[j] = + (gfloat) sc->vptr->rvalue (v_element); + } + +#if DEBUG_MARSHALL + { + glong count = sc->vptr->vector_length (vector); + g_printerr (" float vector has %ld elements\n", count); + if (count > 0) + { + g_printerr (" "); + for (j = 0; j < count; ++j) + g_printerr (" %f", + sc->vptr->rvalue ( sc->vptr->vector_elem (vector, j) )); + g_printerr ("\n"); + } + } +#endif + } + break; + + case GIMP_PDB_STRINGARRAY: + vector = sc->vptr->pair_car (a); /* vector is pointing to a list */ + if (!sc->vptr->is_list (sc, vector)) + success = FALSE; + if (success) + { + n_elements = args[i - 1].data.d_int32; + if (n_elements < 0 || + n_elements > sc->vptr->list_length (sc, vector)) + { + g_snprintf (error_str, sizeof (error_str), + "STRING vector (argument %d) for function %s has " + "length of %d but expected length of %d", + i+1, proc_name, + sc->vptr->list_length (sc, vector), n_elements); + return foreign_error (sc, error_str, 0); + } + + args[i].data.d_stringarray = g_new (gchar *, n_elements); + + for (j = 0; j < n_elements; j++) + { + pointer v_element = sc->vptr->pair_car (vector); + + if (!sc->vptr->is_string (v_element)) + { + g_snprintf (error_str, sizeof (error_str), + "Item %d in vector is not a string (argument %d for function %s)", + j+1, i+1, proc_name); + return foreign_error (sc, error_str, vector); + } + + args[i].data.d_stringarray[j] = + (gchar *) sc->vptr->string_value (v_element); + + vector = sc->vptr->pair_cdr (vector); + } + +#if DEBUG_MARSHALL + { + glong count = sc->vptr->list_length ( sc, sc->vptr->pair_car (a) ); + g_printerr (" string vector has %ld elements\n", count); + if (count > 0) + { + g_printerr (" "); + for (j = 0; j < count; ++j) + g_printerr (" \"%s\"", + args[i].data.d_stringarray[j]); + g_printerr ("\n"); + } + } +#endif + } + break; + + case GIMP_PDB_COLOR: + if (sc->vptr->is_string (sc->vptr->pair_car (a))) + { + if (! gimp_rgb_parse_css (&args[i].data.d_color, + sc->vptr->string_value (sc->vptr->pair_car (a)), + -1)) + success = FALSE; + + gimp_rgb_set_alpha (&args[i].data.d_color, 1.0); +#if DEBUG_MARSHALL + g_printerr (" (%s)\n", + sc->vptr->string_value (sc->vptr->pair_car (a))); +#endif + } + else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) && + sc->vptr->list_length (sc, sc->vptr->pair_car (a)) == 3) + { + pointer color_list; + guchar r = 0, g = 0, b = 0; + + color_list = sc->vptr->pair_car (a); + if (sc->vptr->is_number (sc->vptr->pair_car (color_list))) + r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), + 0, 255); + else + success = FALSE; + + color_list = sc->vptr->pair_cdr (color_list); + if (sc->vptr->is_number (sc->vptr->pair_car (color_list))) + g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), + 0, 255); + else + success = FALSE; + + color_list = sc->vptr->pair_cdr (color_list); + if (sc->vptr->is_number (sc->vptr->pair_car (color_list))) + b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), + 0, 255); + else + success = FALSE; + + if (success) + gimp_rgba_set_uchar (&args[i].data.d_color, r, g, b, 255); +#if DEBUG_MARSHALL + if (success) + g_printerr (" (%d %d %d)\n", r, g, b); + else + g_printerr (" COLOR list contains non-numbers\n"); +#endif + } + else + { + success = FALSE; + } + break; + + case GIMP_PDB_COLORARRAY: + vector = sc->vptr->pair_car (a); + if (!sc->vptr->is_vector (vector)) + success = FALSE; + if (success) + { + n_elements = args[i-1].data.d_int32; + if (n_elements < 0 || + n_elements > sc->vptr->vector_length (vector)) + { + g_snprintf (error_str, sizeof (error_str), + "COLOR vector (argument %d) for function %s has " + "size of %ld but expected size of %d", + i+1, proc_name, + sc->vptr->vector_length (vector), n_elements); + return foreign_error (sc, error_str, 0); + } + + args[i].data.d_colorarray = g_new (GimpRGB, n_elements); + + for (j = 0; j < n_elements; j++) + { + pointer v_element = sc->vptr->vector_elem (vector, j); + pointer color_list; + guchar r, g, b; + + if (! (sc->vptr->is_list (sc, + sc->vptr->pair_car (v_element)) && + sc->vptr->list_length (sc, + sc->vptr->pair_car (v_element)) == 3)) + { + g_snprintf (error_str, sizeof (error_str), + "Item %d in vector is not a color " + "(argument %d for function %s)", + j+1, i+1, proc_name); + return foreign_error (sc, error_str, vector); + } + + color_list = sc->vptr->pair_car (v_element); + r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), + 0, 255); + color_list = sc->vptr->pair_cdr (color_list); + g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), + 0, 255); + color_list = sc->vptr->pair_cdr (color_list); + b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), + 0, 255); + + gimp_rgba_set_uchar (&args[i].data.d_colorarray[j], + r, g, b, 255); + } +#if DEBUG_MARSHALL + { + glong count = sc->vptr->vector_length (vector); + g_printerr (" color vector has %ld elements\n", count); + } +#endif + } + break; + + case GIMP_PDB_PARASITE: + if (!sc->vptr->is_list (sc, sc->vptr->pair_car (a)) || + sc->vptr->list_length (sc, sc->vptr->pair_car (a)) != 3) + success = FALSE; + if (success) + { + pointer temp_val; + + /* parasite->name */ + temp_val = sc->vptr->pair_car (a); + + if (!sc->vptr->is_string (sc->vptr->pair_car (temp_val))) + { + success = FALSE; + break; + } + + args[i].data.d_parasite.name = + sc->vptr->string_value (sc->vptr->pair_car (temp_val)); +#if DEBUG_MARSHALL + g_printerr (" name '%s'\n", args[i].data.d_parasite.name); +#endif + + /* parasite->flags */ + temp_val = sc->vptr->pair_cdr (temp_val); + + if (!sc->vptr->is_number (sc->vptr->pair_car (temp_val))) + { + success = FALSE; + break; + } + + args[i].data.d_parasite.flags = + sc->vptr->ivalue (sc->vptr->pair_car (temp_val)); +#if DEBUG_MARSHALL + g_printerr (" flags %d", args[i].data.d_parasite.flags); +#endif + + /* parasite->data */ + temp_val = sc->vptr->pair_cdr (temp_val); + + if (!sc->vptr->is_string (sc->vptr->pair_car (temp_val))) + { + success = FALSE; + break; + } + + args[i].data.d_parasite.data = + sc->vptr->string_value (sc->vptr->pair_car (temp_val)); + args[i].data.d_parasite.size = strlen (args[i].data.d_parasite.data); + +#if DEBUG_MARSHALL + g_printerr (", size %d\n", args[i].data.d_parasite.size); + g_printerr (" data '%s'\n", (char *)args[i].data.d_parasite.data); +#endif + } + break; + + case GIMP_PDB_STATUS: + return foreign_error (sc, + "Status is for return types, not arguments", + sc->vptr->pair_car (a)); + break; + + default: + g_snprintf (error_str, sizeof (error_str), + "Argument %d for %s is an unknown type", + i+1, proc_name); + return foreign_error (sc, error_str, 0); + } + + /* Break out of loop before i gets updated when error was detected */ + if (! success) + break; + } + + if (success) + { + /* refuse to refresh scripts from a script, better than crashing + * see bug #575830 + */ + if (strcmp (proc_name, "script-fu-refresh-scripts")) + { +#if DEBUG_MARSHALL + g_printerr (" calling %s...", proc_name); +#endif + values = gimp_run_procedure2 (proc_name, &nvalues, nparams, args); +#if DEBUG_MARSHALL + g_printerr (" done.\n"); +#endif + } + } + else + { +#if DEBUG_MARSHALL + g_printerr (" Invalid type for argument %d\n", i+1); +#endif + g_snprintf (error_str, sizeof (error_str), + "Invalid type for argument %d to %s", + i+1, proc_name); + return foreign_error (sc, error_str, 0); + } + + /* Check the return status */ + if (! values) + { +#if DEBUG_MARSHALL + g_printerr (" Did not return status\n"); +#endif + g_snprintf (error_str, sizeof(error_str), + "Procedure execution of %s did not return a status", + proc_name); + + return foreign_error (sc, error_str, 0); + } + +#if DEBUG_MARSHALL + { + const gchar *status_name; + + gimp_enum_get_value (GIMP_TYPE_PDB_STATUS_TYPE, + values[0].data.d_status, + &status_name, NULL, NULL, NULL); + g_printerr (" return value is %s\n", status_name); + } +#endif + + switch (values[0].data.d_status) + { + case GIMP_PDB_EXECUTION_ERROR: + if (nvalues > 1 && values[1].type == GIMP_PDB_STRING) + { + g_snprintf (error_str, sizeof (error_str), + "Procedure execution of %s failed: %s", + proc_name, values[1].data.d_string); + } + else + { + g_snprintf (error_str, sizeof (error_str), + "Procedure execution of %s failed", + proc_name); + } + return foreign_error (sc, error_str, 0); + break; + + case GIMP_PDB_CALLING_ERROR: + if (nvalues > 1 && values[1].type == GIMP_PDB_STRING) + { + g_snprintf (error_str, sizeof (error_str), + "Procedure execution of %s failed on invalid input arguments: %s", + proc_name, values[1].data.d_string); + } + else + { + g_snprintf (error_str, sizeof (error_str), + "Procedure execution of %s failed on invalid input arguments", + proc_name); + } + return foreign_error (sc, error_str, 0); + break; + + case GIMP_PDB_SUCCESS: +#if DEBUG_MARSHALL + g_printerr (" values returned: %d\n", nvalues-1); +#endif + for (i = nvalues - 2; i >= 0; --i) + { + const gchar *string; + gint j; + +#if DEBUG_MARSHALL + { + const gchar *type_name; + + gimp_enum_get_value (GIMP_TYPE_PDB_ARG_TYPE, + return_vals[i].type, + &type_name, NULL, NULL, NULL); + + g_printerr (" value %d is type %s (%d)\n", + i, type_name, return_vals[i].type); + } +#endif + switch (return_vals[i].type) + { + case GIMP_PDB_INT32: + case GIMP_PDB_DISPLAY: + case GIMP_PDB_IMAGE: + case GIMP_PDB_ITEM: + case GIMP_PDB_LAYER: + case GIMP_PDB_CHANNEL: + case GIMP_PDB_DRAWABLE: + case GIMP_PDB_SELECTION: + case GIMP_PDB_VECTORS: + return_val = sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, + values[i + 1].data.d_int32), + return_val); + break; + + case GIMP_PDB_INT16: + return_val = sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, + values[i + 1].data.d_int16), + return_val); + break; + + case GIMP_PDB_INT8: + return_val = sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, + values[i + 1].data.d_int8), + return_val); + break; + + case GIMP_PDB_FLOAT: + return_val = sc->vptr->cons (sc, + sc->vptr->mk_real (sc, + values[i + 1].data.d_float), + return_val); + break; + + case GIMP_PDB_STRING: + string = values[i + 1].data.d_string; + if (! string) + string = ""; + return_val = sc->vptr->cons (sc, + sc->vptr->mk_string (sc, string), + return_val); + break; + + case GIMP_PDB_INT32ARRAY: + { + gint32 num_int32s = values[i].data.d_int32; + gint32 *array = (gint32 *) values[i + 1].data.d_int32array; + pointer vector = sc->vptr->mk_vector (sc, num_int32s); + + for (j = 0; j < num_int32s; j++) + { + sc->vptr->set_vector_elem (vector, j, + sc->vptr->mk_integer (sc, + array[j])); + } + + return_val = sc->vptr->cons (sc, vector, return_val); + } + break; + + case GIMP_PDB_INT16ARRAY: + { + gint32 num_int16s = values[i].data.d_int32; + gint16 *array = (gint16 *) values[i + 1].data.d_int16array; + pointer vector = sc->vptr->mk_vector (sc, num_int16s); + + for (j = 0; j < num_int16s; j++) + { + sc->vptr->set_vector_elem (vector, j, + sc->vptr->mk_integer (sc, + array[j])); + } + + return_val = sc->vptr->cons (sc, vector, return_val); + } + break; + + case GIMP_PDB_INT8ARRAY: + { + gint32 num_int8s = values[i].data.d_int32; + guint8 *array = (guint8 *) values[i + 1].data.d_int8array; + pointer vector = sc->vptr->mk_vector (sc, num_int8s); + + for (j = 0; j < num_int8s; j++) + { + sc->vptr->set_vector_elem (vector, j, + sc->vptr->mk_integer (sc, + array[j])); + } + + return_val = sc->vptr->cons (sc, vector, return_val); + } + break; + + case GIMP_PDB_FLOATARRAY: + { + gint32 num_floats = values[i].data.d_int32; + gdouble *array = (gdouble *) values[i + 1].data.d_floatarray; + pointer vector = sc->vptr->mk_vector (sc, num_floats); + + for (j = 0; j < num_floats; j++) + { + sc->vptr->set_vector_elem (vector, j, + sc->vptr->mk_real (sc, + array[j])); + } + + return_val = sc->vptr->cons (sc, vector, return_val); + } + break; + + case GIMP_PDB_STRINGARRAY: + { + gint num_strings = values[i].data.d_int32; + gchar **array = (gchar **) values[i + 1].data.d_stringarray; + pointer list = sc->NIL; + + for (j = num_strings - 1; j >= 0; j--) + { + list = sc->vptr->cons (sc, + sc->vptr->mk_string (sc, + array[j] ? + array[j] : ""), + list); + } + + return_val = sc->vptr->cons (sc, list, return_val); + } + break; + + case GIMP_PDB_COLOR: + { + guchar r, g, b; + gpointer temp_val; + + gimp_rgb_get_uchar (&values[i + 1].data.d_color, &r, &g, &b); + + temp_val = sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, r), + sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, g), + sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, b), + sc->NIL))); + return_val = sc->vptr->cons (sc, + temp_val, + return_val); + break; + } + + case GIMP_PDB_COLORARRAY: + { + gint32 num_colors = values[i].data.d_int32; + GimpRGB *array = (GimpRGB *) values[i + 1].data.d_colorarray; + pointer vector = sc->vptr->mk_vector (sc, num_colors); + + for (j = 0; j < num_colors; j++) + { + guchar r, g, b; + pointer temp_val; + + gimp_rgb_get_uchar (&array[j], &r, &g, &b); + + temp_val = sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, r), + sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, g), + sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, b), + sc->NIL))); + sc->vptr->set_vector_elem (vector, j, temp_val); + } + + return_val = sc->vptr->cons (sc, vector, return_val); + } + break; + + case GIMP_PDB_PARASITE: + { + if (values[i + 1].data.d_parasite.name == NULL) + { + return_val = foreign_error (sc, "Error: null parasite", 0); + } + else + { + GimpParasite *p = &values[i + 1].data.d_parasite; + gchar *data = g_strndup (p->data, p->size); + gint char_cnt = g_utf8_strlen (data, p->size); + pointer temp_val; + + /* don't move the mk_foo() calls outside this function call, + * otherwise they might be garbage collected away! + */ + temp_val = sc->vptr->cons (sc, + sc->vptr->mk_string (sc, p->name), + sc->vptr->cons (sc, + sc->vptr->mk_integer (sc, p->flags), + sc->vptr->cons (sc, + sc->vptr->mk_counted_string (sc, + data, + char_cnt), + sc->NIL))); + return_val = sc->vptr->cons (sc, + temp_val, + return_val); + g_free (data); + +#if DEBUG_MARSHALL + g_printerr (" name '%s'\n", p->name); + g_printerr (" flags %d", p->flags); + g_printerr (", size %d\n", p->size); + g_printerr (" data '%.*s'\n", + p->size, (gchar *) p->data); +#endif + } + } + break; + + case GIMP_PDB_STATUS: + return foreign_error (sc, "Procedure execution returned multiple status values", 0); + break; + + default: + return foreign_error (sc, "Unknown return type", 0); + } + } + + case GIMP_PDB_PASS_THROUGH: + case GIMP_PDB_CANCEL: /* should we do something here? */ + break; + } + + /* If we have no return value(s) from PDB call, return + * either TRUE or FALSE to indicate if call succeeded. + */ + if (return_val == sc->NIL) + { + if (values[0].data.d_status == GIMP_PDB_SUCCESS) + return_val = sc->vptr->cons (sc, sc->T, sc->NIL); + else + return_val = sc->vptr->cons (sc, sc->F, sc->NIL); + } + + /* free the proc name */ + g_free (proc_name); + + /* free up the executed procedure return values */ + gimp_destroy_params (values, nvalues); + + /* free up arguments and values */ + script_fu_marshal_destroy_args (args, nparams); + + /* free the query information */ + g_free (proc_blurb); + g_free (proc_help); + g_free (proc_author); + g_free (proc_copyright); + g_free (proc_date); + g_free (params); + g_free (return_vals); + + /* if we're in server mode, listen for additional commands for 10 ms */ + if (script_fu_server_get_mode ()) + script_fu_server_listen (10); + +#ifdef GDK_WINDOWING_WIN32 + /* This seems to help a lot on Windoze. */ + while (gtk_events_pending ()) + gtk_main_iteration (); +#endif + + return return_val; +} + +static pointer +script_fu_marshal_procedure_call_strict (scheme *sc, + pointer a) +{ + return script_fu_marshal_procedure_call (sc, a, FALSE); +} + +static pointer +script_fu_marshal_procedure_call_permissive (scheme *sc, + pointer a) +{ + return script_fu_marshal_procedure_call (sc, a, TRUE); +} + +static void +script_fu_marshal_destroy_args (GimpParam *params, + gint n_params) +{ + gint i; + + for (i = 0; i < n_params; i++) + { + switch (params[i].type) + { + case GIMP_PDB_INT32: + case GIMP_PDB_INT16: + case GIMP_PDB_INT8: + case GIMP_PDB_FLOAT: + case GIMP_PDB_STRING: + break; + + case GIMP_PDB_INT32ARRAY: + g_free (params[i].data.d_int32array); + break; + + case GIMP_PDB_INT16ARRAY: + g_free (params[i].data.d_int16array); + break; + + case GIMP_PDB_INT8ARRAY: + g_free (params[i].data.d_int8array); + break; + + case GIMP_PDB_FLOATARRAY: + g_free (params[i].data.d_floatarray); + break; + + case GIMP_PDB_STRINGARRAY: + g_free (params[i].data.d_stringarray); + break; + + case GIMP_PDB_COLORARRAY: + g_free (params[i].data.d_colorarray); + break; + + case GIMP_PDB_COLOR: + case GIMP_PDB_DISPLAY: + case GIMP_PDB_IMAGE: + case GIMP_PDB_ITEM: + case GIMP_PDB_LAYER: + case GIMP_PDB_CHANNEL: + case GIMP_PDB_DRAWABLE: + case GIMP_PDB_SELECTION: + case GIMP_PDB_VECTORS: + case GIMP_PDB_PARASITE: + case GIMP_PDB_STATUS: + case GIMP_PDB_END: + break; + } + } + + g_free (params); +} + +static pointer +script_fu_register_call (scheme *sc, + pointer a) +{ + return script_fu_add_script (sc, a); +} + +static pointer +script_fu_menu_register_call (scheme *sc, + pointer a) +{ + return script_fu_add_menu (sc, a); +} + +static pointer +script_fu_quit_call (scheme *sc, + pointer a) +{ + script_fu_server_quit (); + + scheme_deinit (sc); + + return sc->NIL; +} + +static pointer +script_fu_nil_call (scheme *sc, + pointer a) +{ + return sc->NIL; +} diff --git a/plug-ins/script-fu/scheme-wrapper.h b/plug-ins/script-fu/scheme-wrapper.h new file mode 100644 index 0000000..9ab44ef --- /dev/null +++ b/plug-ins/script-fu/scheme-wrapper.h @@ -0,0 +1,47 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCHEME_WRAPPER_H__ +#define __SCHEME_WRAPPER_H__ + +#include "tinyscheme/scheme.h" + +void tinyscheme_init (GList *path, + gboolean register_scripts); + +void ts_set_run_mode (GimpRunMode run_mode); + +void ts_set_print_flag (gint print_flag); +void ts_print_welcome (void); + +const gchar * ts_get_success_msg (void); + +void ts_interpret_stdin (void); + +/* if the return value is 0, success. error otherwise. */ +gint ts_interpret_string (const gchar *expr); + +void ts_stdout_output_func (TsOutputType type, + const char *string, + int len, + gpointer user_data); +void ts_gstring_output_func (TsOutputType type, + const char *string, + int len, + gpointer user_data); + +#endif /* __SCHEME_WRAPPER_H__ */ diff --git a/plug-ins/script-fu/script-fu-console.c b/plug-ins/script-fu/script-fu-console.c new file mode 100644 index 0000000..835b3db --- /dev/null +++ b/plug-ins/script-fu/script-fu-console.c @@ -0,0 +1,703 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <errno.h> +#include <string.h> + +#include <glib/gstdio.h> + +#include "libgimp/gimp.h" +#include "libgimp/gimpui.h" + +#include <gdk/gdkkeysyms.h> + +#include "scheme-wrapper.h" +#include "script-fu-console.h" + +#include "script-fu-intl.h" + + +#define TEXT_WIDTH 480 +#define TEXT_HEIGHT 400 + +#define PROC_NAME "plug-in-script-fu-console" + +typedef struct +{ + GtkWidget *dialog; + GtkTextBuffer *console; + GtkWidget *cc; + GtkWidget *text_view; + GtkWidget *proc_browser; + GtkWidget *save_dialog; + + GList *history; + gint history_len; + gint history_cur; + gint history_max; +} ConsoleInterface; + +enum +{ + RESPONSE_CLEAR, + RESPONSE_SAVE +}; + +/* + * Local Functions + */ +static void script_fu_console_interface (void); +static void script_fu_console_response (GtkWidget *widget, + gint response_id, + ConsoleInterface *console); +static void script_fu_console_save_dialog (ConsoleInterface *console); +static void script_fu_console_save_response (GtkWidget *dialog, + gint response_id, + ConsoleInterface *console); + +static void script_fu_browse_callback (GtkWidget *widget, + ConsoleInterface *console); +static void script_fu_browse_response (GtkWidget *widget, + gint response_id, + ConsoleInterface *console); +static void script_fu_browse_row_activated (GtkDialog *dialog); + +static gboolean script_fu_cc_is_empty (ConsoleInterface *console); +static gboolean script_fu_cc_key_function (GtkWidget *widget, + GdkEventKey *event, + ConsoleInterface *console); + +static void script_fu_output_to_console (TsOutputType type, + const gchar *text, + gint len, + gpointer user_data); + +/* + * Function definitions + */ + +void +script_fu_console_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[1]; + + ts_set_print_flag (1); + script_fu_console_interface (); + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_SUCCESS; +} + +static void +script_fu_console_interface (void) +{ + ConsoleInterface console = { 0, }; + GtkWidget *vbox; + GtkWidget *button; + GtkWidget *scrolled_window; + GtkWidget *hbox; + + gimp_ui_init ("script-fu", FALSE); + + console.history_max = 50; + + console.dialog = gimp_dialog_new (_("Script-Fu Console"), + "gimp-script-fu-console", + NULL, 0, + gimp_standard_help_func, PROC_NAME, + + _("_Save"), RESPONSE_SAVE, + _("C_lear"), RESPONSE_CLEAR, + _("_Close"), GTK_RESPONSE_CLOSE, + + NULL); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (console.dialog), + GTK_RESPONSE_CLOSE, + RESPONSE_CLEAR, + RESPONSE_SAVE, + -1); + + g_object_add_weak_pointer (G_OBJECT (console.dialog), + (gpointer) &console.dialog); + + g_signal_connect (console.dialog, "response", + G_CALLBACK (script_fu_console_response), + &console); + + /* The main vbox */ + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (console.dialog))), + vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + /* The output text widget */ + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_ALWAYS); + gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0); + gtk_widget_show (scrolled_window); + + console.console = gtk_text_buffer_new (NULL); + console.text_view = gtk_text_view_new_with_buffer (console.console); + g_object_unref (console.console); + + gtk_text_view_set_editable (GTK_TEXT_VIEW (console.text_view), FALSE); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (console.text_view), + GTK_WRAP_WORD); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW (console.text_view), 6); + gtk_text_view_set_right_margin (GTK_TEXT_VIEW (console.text_view), 6); + gtk_widget_set_size_request (console.text_view, TEXT_WIDTH, TEXT_HEIGHT); + gtk_container_add (GTK_CONTAINER (scrolled_window), console.text_view); + gtk_widget_show (console.text_view); + + gtk_text_buffer_create_tag (console.console, "strong", + "weight", PANGO_WEIGHT_BOLD, + "scale", PANGO_SCALE_LARGE, + NULL); + gtk_text_buffer_create_tag (console.console, "emphasis", + "style", PANGO_STYLE_OBLIQUE, + NULL); + + { + const gchar * const greetings[] = + { + "strong", N_("Welcome to TinyScheme"), + NULL, "\n", + NULL, "Copyright (c) Dimitrios Souflis", + NULL, "\n", + "strong", N_("Script-Fu Console"), + NULL, " - ", + "emphasis", N_("Interactive Scheme Development"), + NULL, "\n" + }; + + GtkTextIter cursor; + gint i; + + gtk_text_buffer_get_end_iter (console.console, &cursor); + + for (i = 0; i < G_N_ELEMENTS (greetings); i += 2) + { + if (greetings[i]) + gtk_text_buffer_insert_with_tags_by_name (console.console, &cursor, + gettext (greetings[i + 1]), + -1, greetings[i], + NULL); + else + gtk_text_buffer_insert (console.console, &cursor, + gettext (greetings[i + 1]), -1); + } + } + + /* The current command */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + console.cc = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (hbox), console.cc, TRUE, TRUE, 0); + gtk_widget_grab_focus (console.cc); + gtk_widget_show (console.cc); + + g_signal_connect (console.cc, "key-press-event", + G_CALLBACK (script_fu_cc_key_function), + &console); + + button = gtk_button_new_with_mnemonic (_("_Browse...")); + gtk_misc_set_padding (GTK_MISC (gtk_bin_get_child (GTK_BIN (button))), 2, 0); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0); + gtk_widget_show (button); + + g_signal_connect (button, "clicked", + G_CALLBACK (script_fu_browse_callback), + &console); + + /* Initialize the history */ + console.history = g_list_append (console.history, NULL); + console.history_len = 1; + + gtk_widget_show (console.dialog); + + gtk_main (); + + if (console.save_dialog) + gtk_widget_destroy (console.save_dialog); + + if (console.dialog) + gtk_widget_destroy (console.dialog); +} + +static void +script_fu_console_response (GtkWidget *widget, + gint response_id, + ConsoleInterface *console) +{ + GtkTextIter start, end; + + switch (response_id) + { + case RESPONSE_CLEAR: + gtk_text_buffer_get_start_iter (console->console, &start); + gtk_text_buffer_get_end_iter (console->console, &end); + gtk_text_buffer_delete (console->console, &start, &end); + break; + + case RESPONSE_SAVE: + script_fu_console_save_dialog (console); + break; + + default: + gtk_main_quit (); + break; + } +} + + +static void +script_fu_console_save_dialog (ConsoleInterface *console) +{ + if (! console->save_dialog) + { + console->save_dialog = + gtk_file_chooser_dialog_new (_("Save Script-Fu Console Output"), + GTK_WINDOW (console->dialog), + GTK_FILE_CHOOSER_ACTION_SAVE, + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (console->save_dialog), + GTK_RESPONSE_OK); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (console->save_dialog), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (console->save_dialog), + TRUE); + + g_object_add_weak_pointer (G_OBJECT (console->save_dialog), + (gpointer) &console->save_dialog); + + g_signal_connect (console->save_dialog, "response", + G_CALLBACK (script_fu_console_save_response), + console); + } + + gtk_window_present (GTK_WINDOW (console->save_dialog)); +} + +static void +script_fu_console_save_response (GtkWidget *dialog, + gint response_id, + ConsoleInterface *console) +{ + GtkTextIter start, end; + + if (response_id == GTK_RESPONSE_OK) + { + gchar *filename; + gchar *str; + FILE *fh; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + fh = g_fopen (filename, "w"); + + if (! fh) + { + g_message (_("Could not open '%s' for writing: %s"), + gimp_filename_to_utf8 (filename), + g_strerror (errno)); + + g_free (filename); + return; + } + + gtk_text_buffer_get_start_iter (console->console, &start); + gtk_text_buffer_get_end_iter (console->console, &end); + + str = gtk_text_buffer_get_text (console->console, &start, &end, FALSE); + + fputs (str, fh); + fclose (fh); + + g_free (str); + } + + gtk_widget_hide (dialog); +} + +static void +script_fu_browse_callback (GtkWidget *widget, + ConsoleInterface *console) +{ + if (! console->proc_browser) + { + console->proc_browser = + gimp_proc_browser_dialog_new (_("Script-Fu Procedure Browser"), + "script-fu-procedure-browser", + gimp_standard_help_func, PROC_NAME, + + _("_Apply"), GTK_RESPONSE_APPLY, + _("_Close"), GTK_RESPONSE_CLOSE, + + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (console->proc_browser), + GTK_RESPONSE_APPLY); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (console->proc_browser), + GTK_RESPONSE_CLOSE, + GTK_RESPONSE_APPLY, + -1); + + g_object_add_weak_pointer (G_OBJECT (console->proc_browser), + (gpointer) &console->proc_browser); + + g_signal_connect (console->proc_browser, "response", + G_CALLBACK (script_fu_browse_response), + console); + g_signal_connect (console->proc_browser, "row-activated", + G_CALLBACK (script_fu_browse_row_activated), + console); + } + + gtk_window_present (GTK_WINDOW (console->proc_browser)); +} + +static void +script_fu_browse_response (GtkWidget *widget, + gint response_id, + ConsoleInterface *console) +{ + GimpProcBrowserDialog *dialog = GIMP_PROC_BROWSER_DIALOG (widget); + gchar *proc_name; + gchar *proc_blurb; + gchar *proc_help; + gchar *proc_author; + gchar *proc_copyright; + gchar *proc_date; + GimpPDBProcType proc_type; + gint n_params; + gint n_return_vals; + GimpParamDef *params; + GimpParamDef *return_vals; + gint i; + GString *text; + + if (response_id != GTK_RESPONSE_APPLY) + { + gtk_widget_destroy (widget); + return; + } + + proc_name = gimp_proc_browser_dialog_get_selected (dialog); + + if (proc_name == NULL) + return; + + gimp_procedural_db_proc_info (proc_name, + &proc_blurb, + &proc_help, + &proc_author, + &proc_copyright, + &proc_date, + &proc_type, + &n_params, + &n_return_vals, + ¶ms, + &return_vals); + + text = g_string_new ("("); + text = g_string_append (text, proc_name); + + for (i = 0; i < n_params; i++) + { + text = g_string_append_c (text, ' '); + text = g_string_append (text, params[i].name); + } + + text = g_string_append_c (text, ')'); + + gtk_window_set_focus (GTK_WINDOW (console->dialog), console->cc); + + gtk_entry_set_text (GTK_ENTRY (console->cc), text->str); + gtk_editable_set_position (GTK_EDITABLE (console->cc), + g_utf8_pointer_to_offset (text->str, + text->str + + strlen (proc_name) + 2)); + + g_string_free (text, TRUE); + + gtk_window_present (GTK_WINDOW (console->dialog)); + + g_free (proc_name); + g_free (proc_blurb); + g_free (proc_help); + g_free (proc_author); + g_free (proc_copyright); + g_free (proc_date); + + gimp_destroy_paramdefs (params, n_params); + gimp_destroy_paramdefs (return_vals, n_return_vals); +} + +static void +script_fu_browse_row_activated (GtkDialog *dialog) +{ + gtk_dialog_response (dialog, GTK_RESPONSE_APPLY); +} + +static gboolean +script_fu_console_idle_scroll_end (GtkWidget *view) +{ + GtkWidget *parent = gtk_widget_get_parent (view); + + if (parent) + { + GtkAdjustment *adj; + + adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (parent)); + + gtk_adjustment_set_value (adj, + gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj)); + } + + g_object_unref (view); + + return FALSE; +} + +static void +script_fu_console_scroll_end (GtkWidget *view) +{ + /* the text view idle updates, so we need to idle scroll too + */ + g_object_ref (view); + + g_idle_add ((GSourceFunc) script_fu_console_idle_scroll_end, view); +} + +static void +script_fu_output_to_console (TsOutputType type, + const gchar *text, + gint len, + gpointer user_data) +{ + ConsoleInterface *console = user_data; + + if (console && console->text_view) + { + GtkTextBuffer *buffer; + GtkTextIter cursor; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (console->text_view)); + + gtk_text_buffer_get_end_iter (buffer, &cursor); + + if (type == TS_OUTPUT_NORMAL) + { + gtk_text_buffer_insert (buffer, &cursor, text, len); + } + else + { + gtk_text_buffer_insert_with_tags_by_name (console->console, &cursor, + text, len, "emphasis", + NULL); + } + + script_fu_console_scroll_end (console->text_view); + } +} + +static gboolean +script_fu_cc_is_empty (ConsoleInterface *console) +{ + const gchar *str; + + if ((str = gtk_entry_get_text (GTK_ENTRY (console->cc))) == NULL) + return TRUE; + + while (*str) + { + if (*str != ' ' && *str != '\t' && *str != '\n') + return FALSE; + + str ++; + } + + return TRUE; +} + +static gboolean +script_fu_cc_key_function (GtkWidget *widget, + GdkEventKey *event, + ConsoleInterface *console) +{ + GList *list; + gint direction = 0; + GtkTextIter cursor; + GString *output; + + switch (event->keyval) + { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_ISO_Enter: + if (script_fu_cc_is_empty (console)) + return TRUE; + + list = g_list_nth (console->history, + (g_list_length (console->history) - 1)); + + if (list->data) + g_free (list->data); + + list->data = g_strdup (gtk_entry_get_text (GTK_ENTRY (console->cc))); + + gtk_text_buffer_get_end_iter (console->console, &cursor); + + gtk_text_buffer_insert (console->console, &cursor, "\n", 1); + gtk_text_buffer_insert_with_tags_by_name (console->console, &cursor, + "> ", 2, + "strong", + NULL); + + gtk_text_buffer_insert (console->console, &cursor, + gtk_entry_get_text (GTK_ENTRY (console->cc)), -1); + gtk_text_buffer_insert (console->console, &cursor, "\n", 1); + + script_fu_console_scroll_end (console->text_view); + + gtk_entry_set_text (GTK_ENTRY (console->cc), ""); + + output = g_string_new (NULL); + ts_register_output_func (ts_gstring_output_func, output); + + gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_PLUGIN); + + if (ts_interpret_string (list->data) != 0) + { + script_fu_output_to_console (TS_OUTPUT_ERROR, + output->str, + output->len, + console); + } + else + { + script_fu_output_to_console (TS_OUTPUT_NORMAL, + output->str, + output->len, + console); + } + + gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_INTERNAL); + + g_string_free (output, TRUE); + + gimp_displays_flush (); + + console->history = g_list_append (console->history, NULL); + + if (console->history_len == console->history_max) + { + console->history = g_list_remove (console->history, + console->history->data); + if (console->history->data) + g_free (console->history->data); + } + else + { + console->history_len++; + } + + console->history_cur = g_list_length (console->history) - 1; + + return TRUE; + break; + + case GDK_KEY_KP_Up: + case GDK_KEY_Up: + direction = -1; + break; + + case GDK_KEY_KP_Down: + case GDK_KEY_Down: + direction = 1; + break; + + case GDK_KEY_P: + case GDK_KEY_p: + if (event->state & GDK_CONTROL_MASK) + direction = -1; + break; + + case GDK_KEY_N: + case GDK_KEY_n: + if (event->state & GDK_CONTROL_MASK) + direction = 1; + break; + + default: + break; + } + + if (direction) + { + /* Make sure we keep track of the current one */ + if (console->history_cur == g_list_length (console->history) - 1) + { + list = g_list_nth (console->history, console->history_cur); + + g_free (list->data); + list->data = g_strdup (gtk_entry_get_text (GTK_ENTRY (console->cc))); + } + + console->history_cur += direction; + + if (console->history_cur < 0) + console->history_cur = 0; + + if (console->history_cur >= console->history_len) + console->history_cur = console->history_len - 1; + + gtk_entry_set_text (GTK_ENTRY (console->cc), + (gchar *) (g_list_nth (console->history, + console->history_cur))->data); + + gtk_editable_set_position (GTK_EDITABLE (console->cc), -1); + + return TRUE; + } + + return FALSE; +} diff --git a/plug-ins/script-fu/script-fu-console.h b/plug-ins/script-fu/script-fu-console.h new file mode 100644 index 0000000..8410a61 --- /dev/null +++ b/plug-ins/script-fu/script-fu-console.h @@ -0,0 +1,29 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_CONSOLE_H__ +#define __SCRIPT_FU_CONSOLE_H__ + + +void script_fu_console_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); + + +#endif /* __SCRIPT_FU_CONSOLE_H__ */ diff --git a/plug-ins/script-fu/script-fu-enums.h b/plug-ins/script-fu/script-fu-enums.h new file mode 100644 index 0000000..581441f --- /dev/null +++ b/plug-ins/script-fu/script-fu-enums.h @@ -0,0 +1,54 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_ENUMS_H__ +#define __SCRIPT_FU_ENUMS_H__ + +/* Typedefs for script-fu argument types */ + +typedef enum +{ + SF_IMAGE = 0, + SF_DRAWABLE, + SF_LAYER, + SF_CHANNEL, + SF_VECTORS, + SF_COLOR, + SF_TOGGLE, + SF_VALUE, + SF_STRING, + SF_ADJUSTMENT, + SF_FONT, + SF_PATTERN, + SF_BRUSH, + SF_GRADIENT, + SF_FILENAME, + SF_DIRNAME, + SF_OPTION, + SF_PALETTE, + SF_TEXT, + SF_ENUM, + SF_DISPLAY +} SFArgType; + +typedef enum +{ + SF_SLIDER = 0, + SF_SPINNER +} SFAdjustmentType; + +#endif /* __SCRIPT_FU_ENUMS__ */ diff --git a/plug-ins/script-fu/script-fu-eval.c b/plug-ins/script-fu/script-fu-eval.c new file mode 100644 index 0000000..6f2e354 --- /dev/null +++ b/plug-ins/script-fu/script-fu-eval.c @@ -0,0 +1,80 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include "libgimp/gimp.h" + +#include "scheme-wrapper.h" +#include "script-fu-eval.h" + +#include "script-fu-intl.h" + + +void +script_fu_eval_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[2]; + GString *output = g_string_new (NULL); + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GimpRunMode run_mode; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + + run_mode = params[0].data.d_int32; + + ts_set_run_mode (run_mode); + ts_register_output_func (ts_gstring_output_func, output); + + switch (run_mode) + { + case GIMP_RUN_NONINTERACTIVE: + if (ts_interpret_string (params[1].data.d_string) != 0) + status = GIMP_PDB_EXECUTION_ERROR; + break; + + case GIMP_RUN_INTERACTIVE: + case GIMP_RUN_WITH_LAST_VALS: + status = GIMP_PDB_CALLING_ERROR; + g_string_assign (output, _("Script-Fu evaluation mode only allows " + "non-interactive invocation")); + break; + + default: + break; + } + + values[0].data.d_status = status; + + if (status != GIMP_PDB_SUCCESS && output->len > 0) + { + *nreturn_vals = 2; + values[1].type = GIMP_PDB_STRING; + values[1].data.d_string = g_string_free (output, FALSE); + } + else + { + g_string_free (output, TRUE); + } +} diff --git a/plug-ins/script-fu/script-fu-eval.h b/plug-ins/script-fu/script-fu-eval.h new file mode 100644 index 0000000..83ec9c4 --- /dev/null +++ b/plug-ins/script-fu/script-fu-eval.h @@ -0,0 +1,29 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_EVAL_H__ +#define __SCRIPT_FU_EVAL_H__ + + +void script_fu_eval_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); + + +#endif /* __SCRIPT_FU_EVAL_H__ */ diff --git a/plug-ins/script-fu/script-fu-interface.c b/plug-ins/script-fu/script-fu-interface.c new file mode 100644 index 0000000..0fa1811 --- /dev/null +++ b/plug-ins/script-fu/script-fu-interface.c @@ -0,0 +1,1070 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#ifdef GDK_WINDOWING_QUARTZ +#import <Cocoa/Cocoa.h> +#elif defined (G_OS_WIN32) +#include <windows.h> +#endif + +#include "tinyscheme/scheme-private.h" +#include "scheme-wrapper.h" + +#include "script-fu-types.h" + +#include "script-fu-interface.h" +#include "script-fu-scripts.h" +#include "script-fu-script.h" + +#include "script-fu-intl.h" + + +#define RESPONSE_RESET 1 + +#define TEXT_WIDTH 100 +#define COLOR_SAMPLE_WIDTH 60 +#define COLOR_SAMPLE_HEIGHT 15 +#define SLIDER_WIDTH 80 + + +typedef struct +{ + GtkWidget *dialog; + + GtkWidget *table; + GtkWidget **widgets; + + GtkWidget *progress_label; + GtkWidget *progress_bar; + + gchar *title; + gchar *last_command; + gint command_count; + gint consec_command_count; +} SFInterface; + + +/* + * Local Functions + */ + +static void script_fu_interface_quit (SFScript *script); + +static void script_fu_response (GtkWidget *widget, + gint response_id, + SFScript *script); +static void script_fu_ok (SFScript *script); +static void script_fu_reset (SFScript *script); + +static void script_fu_file_callback (GtkWidget *widget, + SFFilename *file); +static void script_fu_combo_callback (GtkWidget *widget, + SFOption *option); +static void script_fu_pattern_callback (gpointer data, + const gchar *name, + gint width, + gint height, + gint bytes, + const guchar *mask_data, + gboolean closing); +static void script_fu_gradient_callback (gpointer data, + const gchar *name, + gint width, + const gdouble *mask_data, + gboolean closing); +static void script_fu_font_callback (gpointer data, + const gchar *name, + gboolean closing); +static void script_fu_palette_callback (gpointer data, + const gchar *name, + gboolean closing); +static void script_fu_brush_callback (gpointer data, + const gchar *name, + gdouble opacity, + gint spacing, + GimpLayerMode paint_mode, + gint width, + gint height, + const guchar *mask_data, + gboolean closing); +static void script_fu_flush_events (void); +static void script_fu_activate_main_dialog (void); + + +/* + * Local variables + */ + +static SFInterface *sf_interface = NULL; /* there can only be at most + * one interactive interface + */ + +static GimpPDBStatusType sf_status = GIMP_PDB_SUCCESS; + + +/* + * Function definitions + */ + +gboolean +script_fu_interface_is_active (void) +{ + return (sf_interface != NULL); +} + +void +script_fu_interface_report_cc (const gchar *command) +{ + if (sf_interface == NULL) + return; + + if (sf_interface->last_command && + strcmp (sf_interface->last_command, command) == 0) + { + sf_interface->command_count++; + + if (! g_str_has_prefix (command, "gimp-progress-")) + { + gchar *new_command; + + new_command = g_strdup_printf ("%s <%d>", + command, sf_interface->command_count); + gtk_label_set_text (GTK_LABEL (sf_interface->progress_label), + new_command); + g_free (new_command); + } + } + else + { + sf_interface->command_count = 1; + + g_free (sf_interface->last_command); + sf_interface->last_command = g_strdup (command); + + if (! g_str_has_prefix (command, "gimp-progress-")) + { + gtk_label_set_text (GTK_LABEL (sf_interface->progress_label), + command); + } + else + { + gtk_label_set_text (GTK_LABEL (sf_interface->progress_label), ""); + } + } + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +GimpPDBStatusType +script_fu_interface (SFScript *script, + gint start_arg) +{ + GtkWidget *dialog; + GtkWidget *vbox; + GtkWidget *vbox2; + GtkSizeGroup *group; + GSList *list; + gchar *title; + gint i; + + static gboolean gtk_initted = FALSE; + + /* Simply return if there is already an interface. This is an + * ugly workaround for the fact that we can not process two + * scripts at a time. + */ + if (sf_interface != NULL) + { + gchar *message = + g_strdup_printf ("%s\n\n%s", + _("Script-Fu cannot process two scripts " + "at the same time."), + _("You are already running the \"%s\" script.")); + + g_message (message, sf_interface->title); + g_free (message); + + return GIMP_PDB_CANCEL; + } + + g_return_val_if_fail (script != NULL, FALSE); + + if (!gtk_initted) + { + INIT_I18N(); + + gimp_ui_init ("script-fu", TRUE); + + gtk_initted = TRUE; + } + + sf_status = GIMP_PDB_SUCCESS; + + sf_interface = g_slice_new0 (SFInterface); + + sf_interface->widgets = g_new0 (GtkWidget *, script->n_args); + sf_interface->title = script_fu_script_get_title (script); + + title = g_strdup_printf (_("Script-Fu: %s"), sf_interface->title); + + sf_interface->dialog = dialog = + gimp_dialog_new (title, "gimp-script-fu", + NULL, 0, + gimp_standard_help_func, script->name, + + _("_Reset"), RESPONSE_RESET, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, + + NULL); + g_free (title); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), + RESPONSE_RESET, + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gimp_window_set_transient (GTK_WINDOW (dialog)); + + g_signal_connect (dialog, "response", + G_CALLBACK (script_fu_response), + script); + + g_signal_connect_swapped (dialog, "destroy", + G_CALLBACK (script_fu_interface_quit), + script); + + gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), + vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + /* The argument table */ + sf_interface->table = gtk_table_new (script->n_args - start_arg, 3, FALSE); + + gtk_table_set_col_spacings (GTK_TABLE (sf_interface->table), 6); + gtk_table_set_row_spacings (GTK_TABLE (sf_interface->table), 6); + gtk_box_pack_start (GTK_BOX (vbox), sf_interface->table, FALSE, FALSE, 0); + gtk_widget_show (sf_interface->table); + + group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + for (i = start_arg; i < script->n_args; i++) + { + GtkWidget *widget = NULL; + gchar *label_text; + gfloat label_yalign = 0.5; + gint *ID_ptr = NULL; + gint row = i; + gboolean left_align = FALSE; + SFArg *arg = &script->args[i]; + + row -= start_arg; + + /* we add a colon after the label; + * some languages want an extra space here + */ + label_text = g_strdup_printf (_("%s:"), arg->label); + + switch (arg->type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + switch (arg->type) + { + case SF_IMAGE: + widget = gimp_image_combo_box_new (NULL, NULL); + ID_ptr = &arg->value.sfa_image; + break; + + case SF_DRAWABLE: + widget = gimp_drawable_combo_box_new (NULL, NULL); + ID_ptr = &arg->value.sfa_drawable; + break; + + case SF_LAYER: + widget = gimp_layer_combo_box_new (NULL, NULL); + ID_ptr = &arg->value.sfa_layer; + break; + + case SF_CHANNEL: + widget = gimp_channel_combo_box_new (NULL, NULL); + ID_ptr = &arg->value.sfa_channel; + break; + + case SF_VECTORS: + widget = gimp_vectors_combo_box_new (NULL, NULL); + ID_ptr = &arg->value.sfa_vectors; + break; + + default: + break; + } + + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (widget), *ID_ptr, + G_CALLBACK (gimp_int_combo_box_get_active), + ID_ptr); + break; + + case SF_COLOR: + { + GimpColorConfig *config; + + left_align = TRUE; + widget = gimp_color_button_new (_("Script-Fu Color Selection"), + COLOR_SAMPLE_WIDTH, + COLOR_SAMPLE_HEIGHT, + &arg->value.sfa_color, + GIMP_COLOR_AREA_FLAT); + + gimp_color_button_set_update (GIMP_COLOR_BUTTON (widget), TRUE); + + config = gimp_get_color_configuration (); + gimp_color_button_set_color_config (GIMP_COLOR_BUTTON (widget), + config); + g_object_unref (config); + + g_signal_connect (widget, "color-changed", + G_CALLBACK (gimp_color_button_get_color), + &arg->value.sfa_color); + } + break; + + case SF_TOGGLE: + g_free (label_text); + label_text = NULL; + widget = gtk_check_button_new_with_mnemonic (arg->label); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), + arg->value.sfa_toggle); + + g_signal_connect (widget, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &arg->value.sfa_toggle); + break; + + case SF_VALUE: + case SF_STRING: + widget = gtk_entry_new (); + gtk_widget_set_size_request (widget, TEXT_WIDTH, -1); + gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE); + + gtk_entry_set_text (GTK_ENTRY (widget), arg->value.sfa_value); + break; + + case SF_TEXT: + { + GtkWidget *view; + GtkTextBuffer *buffer; + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), + GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_size_request (widget, TEXT_WIDTH, -1); + + view = gtk_text_view_new (); + gtk_container_add (GTK_CONTAINER (widget), view); + gtk_widget_show (view); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + gtk_text_view_set_editable (GTK_TEXT_VIEW (view), TRUE); + + gtk_text_buffer_set_text (buffer, arg->value.sfa_value, -1); + + label_yalign = 0.0; + } + break; + + case SF_ADJUSTMENT: + switch (arg->default_value.sfa_adjustment.type) + { + case SF_SLIDER: + arg->value.sfa_adjustment.adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (sf_interface->table), + 0, row, + label_text, SLIDER_WIDTH, -1, + arg->value.sfa_adjustment.value, + arg->default_value.sfa_adjustment.lower, + arg->default_value.sfa_adjustment.upper, + arg->default_value.sfa_adjustment.step, + arg->default_value.sfa_adjustment.page, + arg->default_value.sfa_adjustment.digits, + TRUE, 0.0, 0.0, + NULL, NULL); + gtk_entry_set_activates_default (GIMP_SCALE_ENTRY_SPINBUTTON (arg->value.sfa_adjustment.adj), TRUE); + break; + + default: + g_warning ("unexpected adjustment type: %d", + arg->default_value.sfa_adjustment.type); + /* fallthrough */ + + case SF_SPINNER: + left_align = TRUE; + arg->value.sfa_adjustment.adj = (GtkAdjustment *) + gtk_adjustment_new (arg->value.sfa_adjustment.value, + arg->default_value.sfa_adjustment.lower, + arg->default_value.sfa_adjustment.upper, + arg->default_value.sfa_adjustment.step, + arg->default_value.sfa_adjustment.page, + 0); + widget = gimp_spin_button_new (arg->value.sfa_adjustment.adj, + arg->default_value.sfa_adjustment.step, + arg->default_value.sfa_adjustment.digits); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (widget), TRUE); + gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE); + break; + } + + g_signal_connect (arg->value.sfa_adjustment.adj, + "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &arg->value.sfa_adjustment.value); + break; + + case SF_FILENAME: + case SF_DIRNAME: + if (arg->type == SF_FILENAME) + widget = gtk_file_chooser_button_new (_("Script-Fu File Selection"), + GTK_FILE_CHOOSER_ACTION_OPEN); + else + widget = gtk_file_chooser_button_new (_("Script-Fu Folder Selection"), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + + if (arg->value.sfa_file.filename) + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), + arg->value.sfa_file.filename); + + g_signal_connect (widget, "selection-changed", + G_CALLBACK (script_fu_file_callback), + &arg->value.sfa_file); + break; + + case SF_FONT: + widget = gimp_font_select_button_new (_("Script-Fu Font Selection"), + arg->value.sfa_font); + g_signal_connect_swapped (widget, "font-set", + G_CALLBACK (script_fu_font_callback), + &arg->value.sfa_font); + break; + + case SF_PALETTE: + widget = gimp_palette_select_button_new (_("Script-Fu Palette Selection"), + arg->value.sfa_palette); + g_signal_connect_swapped (widget, "palette-set", + G_CALLBACK (script_fu_palette_callback), + &arg->value.sfa_palette); + break; + + case SF_PATTERN: + left_align = TRUE; + widget = gimp_pattern_select_button_new (_("Script-Fu Pattern Selection"), + arg->value.sfa_pattern); + g_signal_connect_swapped (widget, "pattern-set", + G_CALLBACK (script_fu_pattern_callback), + &arg->value.sfa_pattern); + break; + + case SF_GRADIENT: + left_align = TRUE; + widget = gimp_gradient_select_button_new (_("Script-Fu Gradient Selection"), + arg->value.sfa_gradient); + g_signal_connect_swapped (widget, "gradient-set", + G_CALLBACK (script_fu_gradient_callback), + &arg->value.sfa_gradient); + break; + + case SF_BRUSH: + left_align = TRUE; + widget = gimp_brush_select_button_new (_("Script-Fu Brush Selection"), + arg->value.sfa_brush.name, + arg->value.sfa_brush.opacity, + arg->value.sfa_brush.spacing, + arg->value.sfa_brush.paint_mode); + g_signal_connect_swapped (widget, "brush-set", + G_CALLBACK (script_fu_brush_callback), + &arg->value.sfa_brush); + break; + + case SF_OPTION: + widget = gtk_combo_box_text_new (); + for (list = arg->default_value.sfa_option.list; + list; + list = g_slist_next (list)) + { + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), + list->data); + } + + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), + arg->value.sfa_option.history); + + g_signal_connect (widget, "changed", + G_CALLBACK (script_fu_combo_callback), + &arg->value.sfa_option); + break; + + case SF_ENUM: + widget = gimp_enum_combo_box_new (g_type_from_name (arg->default_value.sfa_enum.type_name)); + + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (widget), + arg->value.sfa_enum.history); + + g_signal_connect (widget, "changed", + G_CALLBACK (gimp_int_combo_box_get_active), + &arg->value.sfa_enum.history); + break; + + case SF_DISPLAY: + break; + } + + if (widget) + { + if (label_text) + { + gimp_table_attach_aligned (GTK_TABLE (sf_interface->table), + 0, row, + label_text, 0.0, label_yalign, + widget, 2, left_align); + g_free (label_text); + } + else + { + gtk_table_attach (GTK_TABLE (sf_interface->table), + widget, 0, 3, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (widget); + } + + if (left_align) + gtk_size_group_add_widget (group, widget); + } + + sf_interface->widgets[i] = widget; + } + + g_object_unref (group); + + /* the script progress bar */ + vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_end (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0); + gtk_widget_show (vbox2); + + sf_interface->progress_bar = gimp_progress_bar_new (); + gtk_box_pack_start (GTK_BOX (vbox2), sf_interface->progress_bar, + FALSE, FALSE, 0); + gtk_widget_show (sf_interface->progress_bar); + + sf_interface->progress_label = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (sf_interface->progress_label), 0.0); + gtk_label_set_ellipsize (GTK_LABEL (sf_interface->progress_label), + PANGO_ELLIPSIZE_MIDDLE); + gimp_label_set_attributes (GTK_LABEL (sf_interface->progress_label), + PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, + -1); + gtk_box_pack_start (GTK_BOX (vbox2), sf_interface->progress_label, + FALSE, FALSE, 0); + gtk_widget_show (sf_interface->progress_label); +#ifdef G_OS_WIN32 + { + HWND foreground = GetForegroundWindow (); +#endif + + gtk_widget_show (dialog); + + gtk_main (); + +#ifdef G_OS_WIN32 + if (! GetForegroundWindow ()) + SetForegroundWindow (foreground); + } +#endif + return sf_status; +} + +static void +script_fu_interface_quit (SFScript *script) +{ + gint i; + + g_return_if_fail (script != NULL); + g_return_if_fail (sf_interface != NULL); + + g_free (sf_interface->title); + + for (i = 0; i < script->n_args; i++) + switch (script->args[i].type) + { + case SF_FONT: + case SF_PALETTE: + case SF_PATTERN: + case SF_GRADIENT: + case SF_BRUSH: + gimp_select_button_close_popup + (GIMP_SELECT_BUTTON (sf_interface->widgets[i])); + break; + + default: + break; + } + + g_free (sf_interface->widgets); + g_free (sf_interface->last_command); + + g_slice_free (SFInterface, sf_interface); + sf_interface = NULL; + + /* We do not call gtk_main_quit() earlier to reduce the possibility + * that script_fu_script_proc() is called from gimp_extension_process() + * while we are not finished with the current script. This sucks! + */ + + gtk_main_quit (); +} + +static void +script_fu_file_callback (GtkWidget *widget, + SFFilename *file) +{ + if (file->filename) + g_free (file->filename); + + file->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + script_fu_activate_main_dialog (); +} + +static void +script_fu_combo_callback (GtkWidget *widget, + SFOption *option) +{ + option->history = gtk_combo_box_get_active (GTK_COMBO_BOX (widget)); +} + +static void +script_fu_string_update (gchar **dest, + const gchar *src) +{ + if (*dest) + g_free (*dest); + + *dest = g_strdup (src); +} + +static void +script_fu_pattern_callback (gpointer data, + const gchar *name, + gint width, + gint height, + gint bytes, + const guchar *mask_data, + gboolean closing) +{ + script_fu_string_update (data, name); + if (closing) script_fu_activate_main_dialog (); +} + +static void +script_fu_gradient_callback (gpointer data, + const gchar *name, + gint width, + const gdouble *mask_data, + gboolean closing) +{ + script_fu_string_update (data, name); + if (closing) script_fu_activate_main_dialog (); +} + +static void +script_fu_font_callback (gpointer data, + const gchar *name, + gboolean closing) +{ + script_fu_string_update (data, name); + if (closing) script_fu_activate_main_dialog (); +} + +static void +script_fu_palette_callback (gpointer data, + const gchar *name, + gboolean closing) +{ + script_fu_string_update (data, name); + if (closing) script_fu_activate_main_dialog (); +} + +static void +script_fu_brush_callback (gpointer data, + const gchar *name, + gdouble opacity, + gint spacing, + GimpLayerMode paint_mode, + gint width, + gint height, + const guchar *mask_data, + gboolean closing) +{ + SFBrush *brush = data; + + g_free (brush->name); + + brush->name = g_strdup (name); + brush->opacity = opacity; + brush->spacing = spacing; + brush->paint_mode = paint_mode; + + if (closing) script_fu_activate_main_dialog (); +} + +static void +unset_transient_for (GtkWidget *dialog) +{ + GdkWindow *window = gtk_widget_get_window (dialog); + + if (window) + gdk_property_delete (window, + gdk_atom_intern_static_string ("WM_TRANSIENT_FOR")); +} + +static void +script_fu_response (GtkWidget *widget, + gint response_id, + SFScript *script) +{ + GtkWidget *action_area; + + action_area = gtk_dialog_get_action_area (GTK_DIALOG (sf_interface->dialog)); + + if (! gtk_widget_is_sensitive (action_area)) + return; + + switch (response_id) + { + case RESPONSE_RESET: + script_fu_reset (script); + break; + + case GTK_RESPONSE_OK: + gtk_widget_set_sensitive (sf_interface->table, FALSE); + gtk_widget_set_sensitive (action_area, FALSE); + + script_fu_ok (script); + + script_fu_flush_events (); + /* + * The script could have created a new GimpImageWindow, so + * unset the transient-for property not to focus the + * ImageWindow from which the script was started + */ + unset_transient_for (sf_interface->dialog); + + gtk_widget_destroy (sf_interface->dialog); + break; + + default: + sf_status = GIMP_PDB_CANCEL; + + script_fu_flush_events (); + gtk_widget_destroy (sf_interface->dialog); + break; + } + + script_fu_flush_events (); +} + +static void +script_fu_ok (SFScript *script) +{ + GString *output; + gchar *command; + gint i; + + for (i = 0; i < script->n_args; i++) + { + SFArgValue *arg_value = &script->args[i].value; + GtkWidget *widget = sf_interface->widgets[i]; + + switch (script->args[i].type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + case SF_COLOR: + case SF_TOGGLE: + break; + + case SF_VALUE: + case SF_STRING: + g_free (arg_value->sfa_value); + arg_value->sfa_value = + g_strdup (gtk_entry_get_text (GTK_ENTRY (widget))); + break; + + case SF_TEXT: + { + GtkWidget *view; + GtkTextBuffer *buffer; + GtkTextIter start, end; + + view = gtk_bin_get_child (GTK_BIN (widget)); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + gtk_text_buffer_get_start_iter (buffer, &start); + gtk_text_buffer_get_end_iter (buffer, &end); + + g_free (arg_value->sfa_value); + arg_value->sfa_value = gtk_text_buffer_get_text (buffer, + &start, &end, + FALSE); + } + break; + + case SF_ADJUSTMENT: + case SF_FILENAME: + case SF_DIRNAME: + case SF_FONT: + case SF_PALETTE: + case SF_PATTERN: + case SF_GRADIENT: + case SF_BRUSH: + case SF_OPTION: + case SF_ENUM: + break; + } + } + + command = script_fu_script_get_command (script); + + /* run the command through the interpreter */ + output = g_string_new (NULL); + ts_register_output_func (ts_gstring_output_func, output); + + gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_PLUGIN); + + if (ts_interpret_string (command)) + { + gchar *message = g_strdup_printf (_("Error while executing %s:"), + script->name); + + g_message ("%s\n\n%s", message, output->str); + g_free (message); + } + + gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_INTERNAL); + + g_string_free (output, TRUE); + + g_free (command); +} + +static void +script_fu_reset (SFScript *script) +{ + gint i; + + script_fu_script_reset (script, FALSE); + + for (i = 0; i < script->n_args; i++) + { + SFArgValue *value = &script->args[i].value; + GtkWidget *widget = sf_interface->widgets[i]; + + switch (script->args[i].type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + break; + + case SF_COLOR: + gimp_color_button_set_color (GIMP_COLOR_BUTTON (widget), + &value->sfa_color); + break; + + case SF_TOGGLE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), + value->sfa_toggle); + break; + + case SF_VALUE: + case SF_STRING: + gtk_entry_set_text (GTK_ENTRY (widget), value->sfa_value); + break; + + case SF_TEXT: + { + GtkWidget *view; + GtkTextBuffer *buffer; + + view = gtk_bin_get_child (GTK_BIN (widget)); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + gtk_text_buffer_set_text (buffer, value->sfa_value, -1); + } + break; + + case SF_ADJUSTMENT: + gtk_adjustment_set_value (value->sfa_adjustment.adj, + value->sfa_adjustment.value); + break; + + case SF_FILENAME: + case SF_DIRNAME: + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), + value->sfa_file.filename); + break; + + case SF_FONT: + gimp_font_select_button_set_font (GIMP_FONT_SELECT_BUTTON (widget), + value->sfa_font); + break; + + case SF_PALETTE: + gimp_palette_select_button_set_palette (GIMP_PALETTE_SELECT_BUTTON (widget), + value->sfa_palette); + break; + + case SF_PATTERN: + gimp_pattern_select_button_set_pattern (GIMP_PATTERN_SELECT_BUTTON (widget), + value->sfa_pattern); + break; + + case SF_GRADIENT: + gimp_gradient_select_button_set_gradient (GIMP_GRADIENT_SELECT_BUTTON (widget), + value->sfa_gradient); + break; + + case SF_BRUSH: + gimp_brush_select_button_set_brush (GIMP_BRUSH_SELECT_BUTTON (widget), + value->sfa_brush.name, + value->sfa_brush.opacity, + value->sfa_brush.spacing, + value->sfa_brush.paint_mode); + break; + + case SF_OPTION: + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), + value->sfa_option.history); + break; + + case SF_ENUM: + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (widget), + value->sfa_enum.history); + break; + } + } +} + + +/* + * Functions for window front/back management. + * These might only be necessary for MacOS. + * + * One problem is that the GIMP and the scriptfu extension process are separate "apps". + * Closing a main scriptfu dialog does not terminate the scriptfu extension process, + * and MacOS does not then activate some other app. + * On other platforms, the select dialogs are transient to the GIMP app's progress bar, + * but that doesn't seem to work on MacOS. + * + * Also some of the GIMP "select" widgets (for brush, pattern, gradient, font, palette) + * for plugins are independent and tool like: + * their popup dialog window is not a child of the button which pops it up. + * The button "owns" the popup but GDK is not aware of that relation, + * and so does not handle closing automatically. + * There are PDB callbacks in each direction: + * from the select dialog to the scriptfu extension on user's new selection + * from the scriptfu extension to the select dialog on closing + * + * This might change in the future. + * 1) in GIMP 3, scriptfu and python plugins should use a common API for a control dialog, + * (script-fu-interface.c is obsoleted?) + * 2) the code for select dialogs is significantly changed in GIMP 3 + * 3) Gtk3 might solve this (now using Gtk2.) + */ + +/* On MacOS, without calls to this, scriptfu dialog gets spinning ball of doom, + * meaning MacOS thinks app is not responding to events, + * and dialog stays visible even after destroyed. + */ +static void +script_fu_flush_events (void) +{ + /* Ensure all GLib events have been processed. */ + + /* Former code also hid GUI of the script-fu extension process using: [NSApp hide: nil]; + * (In Objective-C, get instance of NSApplication and send it a "hide" message with nil sender.) + * Hiding is not necessary, since this is only called when + * scriptfu is done interpreting the current script and is destroying its widgets. + */ +#ifdef GDK_WINDOWING_QUARTZ + /* Alternative code might be a call to gtk_main()? + * This is not an infinite loop since there are finite events, and iteration reduces them. + * Somehow, this lets MacOS think the app is responsive. + */ + while (g_main_context_pending (NULL)) + g_main_context_iteration (NULL, TRUE); +#else + /* empty function, optimized out. */ +#endif +} + + +/* On MacOS, without calls to this, + * when user closes GIMP "select" dialogs (child of main dialog) + * the main scriptfu dialog can be obscured by GIMP main window. + * The main scriptfu dialog must be visible so user can choose the OK button, + * and it contains a progress bar. + * + * Note the color "select" dialog has no callback specialized for scriptfu. + * And the file "chooser" dialog is also different. + */ +static void +script_fu_activate_main_dialog (void) +{ + /* Ensure the main dialog of the script-fu extension process is not obscured. */ +#ifdef GDK_WINDOWING_QUARTZ + /* In Objective-C, get instance of NSApplication + * and send it a "activateIgnoringOtherApps" message, i.e. bring to front. + */ + [NSApp activateIgnoringOtherApps: YES]; +#else + /* empty function, optimized out. */ +#endif +} diff --git a/plug-ins/script-fu/script-fu-interface.h b/plug-ins/script-fu/script-fu-interface.h new file mode 100644 index 0000000..3d5091c --- /dev/null +++ b/plug-ins/script-fu/script-fu-interface.h @@ -0,0 +1,28 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_INTERFACE_H__ +#define __SCRIPT_FU_INTERFACE_H__ + + +GimpPDBStatusType script_fu_interface (SFScript *script, + gint start_arg); +void script_fu_interface_report_cc (const gchar *command); +gboolean script_fu_interface_is_active (void); + + +#endif /* __SCRIPT_FU_INTERFACE_H__ */ diff --git a/plug-ins/script-fu/script-fu-intl.h b/plug-ins/script-fu/script-fu-intl.h new file mode 100644 index 0000000..462582c --- /dev/null +++ b/plug-ins/script-fu/script-fu-intl.h @@ -0,0 +1,43 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * script-fu-intl.h + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_INTL_H__ +#define __SCRIPT_FU_INTL_H__ + +#ifndef GETTEXT_PACKAGE +#error "config.h must be included prior to script-fu-intl.h" +#endif + +#include <glib/gi18n.h> + + +#ifndef HAVE_BIND_TEXTDOMAIN_CODESET +# define bind_textdomain_codeset(Domain, Codeset) (Domain) +#endif + +#define INIT_I18N() G_STMT_START{ \ + bindtextdomain (GETTEXT_PACKAGE"-script-fu", \ + gimp_locale_directory ()); \ + bind_textdomain_codeset (GETTEXT_PACKAGE"-script-fu", "UTF-8"); \ + textdomain (GETTEXT_PACKAGE"-script-fu"); \ +}G_STMT_END + + +#endif /* __SCRIPT_FU_INTL_H__ */ diff --git a/plug-ins/script-fu/script-fu-regex.c b/plug-ins/script-fu/script-fu-regex.c new file mode 100644 index 0000000..02255d2 --- /dev/null +++ b/plug-ins/script-fu/script-fu-regex.c @@ -0,0 +1,179 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +/* Based on re.c + * + * Henry Spencer's implementation of Regular Expressions, + * used for TinyScheme + * + * Refurbished by Stephen Gildea + * + * Ported to GRegex and de-uglified by Michael Natterer + */ + +#include "config.h" + +#include "tinyscheme/scheme-private.h" +#include "script-fu-regex.h" + + +/* local function prototypes */ + +static pointer foreign_re_match (scheme *sc, + pointer args); +static void set_vector_elem (pointer vec, + int ielem, + pointer newel); + + +/* public functions */ + +void +script_fu_regex_init (scheme *sc) +{ + sc->vptr->scheme_define (sc, + sc->global_env, + sc->vptr->mk_symbol(sc,"re-match"), + sc->vptr->mk_foreign_func(sc, foreign_re_match)); + +#if 0 + sc->vptr->load_string + (sc, + ";; return the substring of STRING matched in MATCH-VECTOR,\n" + ";; the Nth subexpression match (default 0).\n" + "\n" + "(define (re-match-nth string match-vector . n)\n" + " (let ((n (if (pair? n) (car n) 0)))\n" + " (substring string (car (vector-ref match-vector n))\n" + " (cdr (vector-ref match-vector n)))))\n" + "(define (re-before-nth string match-vector . n)\n" + " (let ((n (if (pair? n) (car n) 0)))\n" + " (substring string 0 (car (vector-ref match-vector n)))))\n" + "(define (re-after-nth string match-vector . n)\n" + " (let ((n (if (pair? n) (car n) 0)))\n" + " (substring string (cdr (vector-ref match-vector n))\n" + " (string-length string))))\n"); +#endif +} + + +/* private functions */ + +static pointer +foreign_re_match (scheme *sc, + pointer args) +{ + pointer retval = sc->F; + gboolean success; + gboolean is_valid_utf8; + GRegex *regex; + pointer first_arg, second_arg; + pointer third_arg = sc->NIL; + char *string; + char *pattern; + int num = 0; + + if (!((args != sc->NIL) + && sc->vptr->is_string ((first_arg = sc->vptr->pair_car (args))) + && (args = sc->vptr->pair_cdr (args)) + && sc->vptr->is_pair (args) + && sc->vptr->is_string ((second_arg = sc->vptr->pair_car (args))))) + { + return sc->F; + } + + pattern = sc->vptr->string_value (first_arg); + string = sc->vptr->string_value (second_arg); + + is_valid_utf8 = g_utf8_validate (string, -1, NULL); + + args = sc->vptr->pair_cdr (args); + + if (args != sc->NIL) + { + if (!(sc->vptr->is_pair (args) + && sc->vptr->is_vector ((third_arg = sc->vptr->pair_car (args))))) + { + return sc->F; + } + else + { + num = third_arg->_object._number.value.ivalue; + } + } + + regex = g_regex_new (pattern, G_REGEX_EXTENDED, 0, NULL); + if (! regex) + return sc->F; + + if (! num) + { + success = g_regex_match (regex, string, 0, NULL); + } + else + { + GMatchInfo *match_info; + gint i; + + success = g_regex_match (regex, string, 0, &match_info); + + for (i = 0; i < num; i++) + { + gint start, end; + + g_match_info_fetch_pos (match_info, i, &start, &end); + + if (is_valid_utf8) + { + start = g_utf8_pointer_to_offset (string, string + start); + end = g_utf8_pointer_to_offset (string, string + end); + } + +#undef cons + set_vector_elem (third_arg, i, + sc->vptr->cons(sc, + sc->vptr->mk_integer(sc, start), + sc->vptr->mk_integer(sc, end))); + } + + g_match_info_free (match_info); + } + + if (success) + retval = sc->T; + + g_regex_unref (regex); + + return retval; +} + +static void +set_vector_elem (pointer vec, + int ielem, + pointer newel) +{ + int n = ielem / 2; + + if (ielem % 2 == 0) + { + vec[1 + n]._object._cons._car = newel; + } + else + { + vec[1 + n]._object._cons._cdr = newel; + } +} diff --git a/plug-ins/script-fu/script-fu-regex.h b/plug-ins/script-fu/script-fu-regex.h new file mode 100644 index 0000000..9c0cbb2 --- /dev/null +++ b/plug-ins/script-fu/script-fu-regex.h @@ -0,0 +1,25 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_REGEX_H__ +#define __SCRIPT_FU_REGEX_H__ + + +void script_fu_regex_init (scheme *sc); + + +#endif /* __SCRIPT_FU_REGEX_H__ */ diff --git a/plug-ins/script-fu/script-fu-script.c b/plug-ins/script-fu/script-fu-script.c new file mode 100644 index 0000000..cd37163 --- /dev/null +++ b/plug-ins/script-fu/script-fu-script.c @@ -0,0 +1,780 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "tinyscheme/scheme-private.h" + +#include "script-fu-types.h" + +#include "script-fu-script.h" +#include "script-fu-scripts.h" +#include "script-fu-utils.h" + +#include "script-fu-intl.h" + + +/* + * Local Functions + */ + +static gboolean script_fu_script_param_init (SFScript *script, + gint nparams, + const GimpParam *params, + SFArgType type, + gint n); + + +/* + * Function definitions + */ + +SFScript * +script_fu_script_new (const gchar *name, + const gchar *menu_label, + const gchar *blurb, + const gchar *author, + const gchar *copyright, + const gchar *date, + const gchar *image_types, + gint n_args) +{ + SFScript *script; + + script = g_slice_new0 (SFScript); + + script->name = g_strdup (name); + script->menu_label = g_strdup (menu_label); + script->blurb = g_strdup (blurb); + script->author = g_strdup (author); + script->copyright = g_strdup (copyright); + script->date = g_strdup (date); + script->image_types = g_strdup (image_types); + + script->n_args = n_args; + script->args = g_new0 (SFArg, script->n_args); + + return script; +} + +void +script_fu_script_free (SFScript *script) +{ + gint i; + + g_return_if_fail (script != NULL); + + g_free (script->name); + g_free (script->blurb); + g_free (script->menu_label); + g_free (script->author); + g_free (script->copyright); + g_free (script->date); + g_free (script->image_types); + + for (i = 0; i < script->n_args; i++) + { + SFArg *arg = &script->args[i]; + + g_free (arg->label); + + switch (arg->type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + case SF_COLOR: + case SF_TOGGLE: + break; + + case SF_VALUE: + case SF_STRING: + case SF_TEXT: + g_free (arg->default_value.sfa_value); + g_free (arg->value.sfa_value); + break; + + case SF_ADJUSTMENT: + break; + + case SF_FILENAME: + case SF_DIRNAME: + g_free (arg->default_value.sfa_file.filename); + g_free (arg->value.sfa_file.filename); + break; + + case SF_FONT: + g_free (arg->default_value.sfa_font); + g_free (arg->value.sfa_font); + break; + + case SF_PALETTE: + g_free (arg->default_value.sfa_palette); + g_free (arg->value.sfa_palette); + break; + + case SF_PATTERN: + g_free (arg->default_value.sfa_pattern); + g_free (arg->value.sfa_pattern); + break; + + case SF_GRADIENT: + g_free (arg->default_value.sfa_gradient); + g_free (arg->value.sfa_gradient); + break; + + case SF_BRUSH: + g_free (arg->default_value.sfa_brush.name); + g_free (arg->value.sfa_brush.name); + break; + + case SF_OPTION: + g_slist_free_full (arg->default_value.sfa_option.list, + (GDestroyNotify) g_free); + break; + + case SF_ENUM: + g_free (arg->default_value.sfa_enum.type_name); + break; + } + } + + g_free (script->args); + + g_slice_free (SFScript, script); +} + +void +script_fu_script_install_proc (SFScript *script, + GimpRunProc run_proc) +{ + const gchar *menu_label = NULL; + GimpParamDef *args; + gint i; + + g_return_if_fail (script != NULL); + g_return_if_fail (run_proc != NULL); + + /* Allow scripts with no menus */ + if (strncmp (script->menu_label, "<None>", 6) != 0) + menu_label = script->menu_label; + + args = g_new0 (GimpParamDef, script->n_args + 1); + + args[0].type = GIMP_PDB_INT32; + args[0].name = "run-mode"; + args[0].description = "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }"; + + for (i = 0; i < script->n_args; i++) + { + GimpPDBArgType type = 0; + const gchar *name = NULL; + + switch (script->args[i].type) + { + case SF_IMAGE: + type = GIMP_PDB_IMAGE; + name = "image"; + break; + + case SF_DRAWABLE: + type = GIMP_PDB_DRAWABLE; + name = "drawable"; + break; + + case SF_LAYER: + type = GIMP_PDB_LAYER; + name = "layer"; + break; + + case SF_CHANNEL: + type = GIMP_PDB_CHANNEL; + name = "channel"; + break; + + case SF_VECTORS: + type = GIMP_PDB_VECTORS; + name = "vectors"; + break; + + case SF_DISPLAY: + type = GIMP_PDB_DISPLAY; + name = "display"; + break; + + case SF_COLOR: + type = GIMP_PDB_COLOR; + name = "color"; + break; + + case SF_TOGGLE: + type = GIMP_PDB_INT32; + name = "toggle"; + break; + + case SF_VALUE: + type = GIMP_PDB_STRING; + name = "value"; + break; + + case SF_STRING: + case SF_TEXT: + type = GIMP_PDB_STRING; + name = "string"; + break; + + case SF_ADJUSTMENT: + type = GIMP_PDB_FLOAT; + name = "value"; + break; + + case SF_FILENAME: + type = GIMP_PDB_STRING; + name = "filename"; + break; + + case SF_DIRNAME: + type = GIMP_PDB_STRING; + name = "dirname"; + break; + + case SF_FONT: + type = GIMP_PDB_STRING; + name = "font"; + break; + + case SF_PALETTE: + type = GIMP_PDB_STRING; + name = "palette"; + break; + + case SF_PATTERN: + type = GIMP_PDB_STRING; + name = "pattern"; + break; + + case SF_BRUSH: + type = GIMP_PDB_STRING; + name = "brush"; + break; + + case SF_GRADIENT: + type = GIMP_PDB_STRING; + name = "gradient"; + break; + + case SF_OPTION: + type = GIMP_PDB_INT32; + name = "option"; + break; + + case SF_ENUM: + type = GIMP_PDB_INT32; + name = "enum"; + break; + } + + args[i + 1].type = type; + args[i + 1].name = (gchar *) name; + args[i + 1].description = script->args[i].label; + } + + gimp_install_temp_proc (script->name, + script->blurb, + "", + script->author, + script->copyright, + script->date, + menu_label, + script->image_types, + GIMP_TEMPORARY, + script->n_args + 1, 0, + args, NULL, + run_proc); + + g_free (args); +} + +void +script_fu_script_uninstall_proc (SFScript *script) +{ + g_return_if_fail (script != NULL); + + gimp_uninstall_temp_proc (script->name); +} + +gchar * +script_fu_script_get_title (SFScript *script) +{ + gchar *title; + gchar *tmp; + + g_return_val_if_fail (script != NULL, NULL); + + /* strip mnemonics from the menupath */ + title = gimp_strip_uline (script->menu_label); + + /* if this looks like a full menu path, use only the last part */ + if (title[0] == '<' && (tmp = strrchr (title, '/')) && tmp[1]) + { + tmp = g_strdup (tmp + 1); + + g_free (title); + title = tmp; + } + + /* cut off ellipsis */ + tmp = (strstr (title, "...")); + if (! tmp) + /* U+2026 HORIZONTAL ELLIPSIS */ + tmp = strstr (title, "\342\200\246"); + + if (tmp && tmp == (title + strlen (title) - 3)) + *tmp = '\0'; + + return title; +} + +void +script_fu_script_reset (SFScript *script, + gboolean reset_ids) +{ + gint i; + + g_return_if_fail (script != NULL); + + for (i = 0; i < script->n_args; i++) + { + SFArgValue *value = &script->args[i].value; + SFArgValue *default_value = &script->args[i].default_value; + + switch (script->args[i].type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + if (reset_ids) + value->sfa_image = default_value->sfa_image; + break; + + case SF_COLOR: + value->sfa_color = default_value->sfa_color; + break; + + case SF_TOGGLE: + value->sfa_toggle = default_value->sfa_toggle; + break; + + case SF_VALUE: + case SF_STRING: + case SF_TEXT: + g_free (value->sfa_value); + value->sfa_value = g_strdup (default_value->sfa_value); + break; + + case SF_ADJUSTMENT: + value->sfa_adjustment.value = default_value->sfa_adjustment.value; + break; + + case SF_FILENAME: + case SF_DIRNAME: + g_free (value->sfa_file.filename); + value->sfa_file.filename = g_strdup (default_value->sfa_file.filename); + break; + + case SF_FONT: + g_free (value->sfa_font); + value->sfa_font = g_strdup (default_value->sfa_font); + break; + + case SF_PALETTE: + g_free (value->sfa_palette); + value->sfa_palette = g_strdup (default_value->sfa_palette); + break; + + case SF_PATTERN: + g_free (value->sfa_pattern); + value->sfa_pattern = g_strdup (default_value->sfa_pattern); + break; + + case SF_GRADIENT: + g_free (value->sfa_gradient); + value->sfa_gradient = g_strdup (default_value->sfa_gradient); + break; + + case SF_BRUSH: + g_free (value->sfa_brush.name); + value->sfa_brush.name = g_strdup (default_value->sfa_brush.name); + value->sfa_brush.opacity = default_value->sfa_brush.opacity; + value->sfa_brush.spacing = default_value->sfa_brush.spacing; + value->sfa_brush.paint_mode = default_value->sfa_brush.paint_mode; + break; + + case SF_OPTION: + value->sfa_option.history = default_value->sfa_option.history; + break; + + case SF_ENUM: + value->sfa_enum.history = default_value->sfa_enum.history; + break; + } + } +} + +gint +script_fu_script_collect_standard_args (SFScript *script, + gint n_params, + const GimpParam *params) +{ + gint params_consumed = 0; + + g_return_val_if_fail (script != NULL, 0); + + /* the first parameter may be a DISPLAY id */ + if (script_fu_script_param_init (script, + n_params, params, SF_DISPLAY, + params_consumed)) + { + params_consumed++; + } + + /* an IMAGE id may come first or after the DISPLAY id */ + if (script_fu_script_param_init (script, + n_params, params, SF_IMAGE, + params_consumed)) + { + params_consumed++; + + /* and may be followed by a DRAWABLE, LAYER, CHANNEL or + * VECTORS id + */ + if (script_fu_script_param_init (script, + n_params, params, SF_DRAWABLE, + params_consumed) || + script_fu_script_param_init (script, + n_params, params, SF_LAYER, + params_consumed) || + script_fu_script_param_init (script, + n_params, params, SF_CHANNEL, + params_consumed) || + script_fu_script_param_init (script, + n_params, params, SF_VECTORS, + params_consumed)) + { + params_consumed++; + } + } + + return params_consumed; +} + +gchar * +script_fu_script_get_command (SFScript *script) +{ + GString *s; + gint i; + + g_return_val_if_fail (script != NULL, NULL); + + s = g_string_new ("("); + g_string_append (s, script->name); + + for (i = 0; i < script->n_args; i++) + { + SFArgValue *arg_value = &script->args[i].value; + + g_string_append_c (s, ' '); + + switch (script->args[i].type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + g_string_append_printf (s, "%d", arg_value->sfa_image); + break; + + case SF_COLOR: + { + guchar r, g, b; + + gimp_rgb_get_uchar (&arg_value->sfa_color, &r, &g, &b); + g_string_append_printf (s, "'(%d %d %d)", + (gint) r, (gint) g, (gint) b); + } + break; + + case SF_TOGGLE: + g_string_append (s, arg_value->sfa_toggle ? "TRUE" : "FALSE"); + break; + + case SF_VALUE: + g_string_append (s, arg_value->sfa_value); + break; + + case SF_STRING: + case SF_TEXT: + { + gchar *tmp; + + tmp = script_fu_strescape (arg_value->sfa_value); + g_string_append_printf (s, "\"%s\"", tmp); + g_free (tmp); + } + break; + + case SF_ADJUSTMENT: + { + gchar buffer[G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (buffer, sizeof (buffer), + arg_value->sfa_adjustment.value); + g_string_append (s, buffer); + } + break; + + case SF_FILENAME: + case SF_DIRNAME: + { + gchar *tmp; + + tmp = script_fu_strescape (arg_value->sfa_file.filename); + g_string_append_printf (s, "\"%s\"", tmp); + g_free (tmp); + } + break; + + case SF_FONT: + g_string_append_printf (s, "\"%s\"", arg_value->sfa_font); + break; + + case SF_PALETTE: + g_string_append_printf (s, "\"%s\"", arg_value->sfa_palette); + break; + + case SF_PATTERN: + g_string_append_printf (s, "\"%s\"", arg_value->sfa_pattern); + break; + + case SF_GRADIENT: + g_string_append_printf (s, "\"%s\"", arg_value->sfa_gradient); + break; + + case SF_BRUSH: + { + gchar buffer[G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (buffer, sizeof (buffer), + arg_value->sfa_brush.opacity); + g_string_append_printf (s, "'(\"%s\" %s %d %d)", + arg_value->sfa_brush.name, + buffer, + arg_value->sfa_brush.spacing, + arg_value->sfa_brush.paint_mode); + } + break; + + case SF_OPTION: + g_string_append_printf (s, "%d", arg_value->sfa_option.history); + break; + + case SF_ENUM: + g_string_append_printf (s, "%d", arg_value->sfa_enum.history); + break; + } + } + + g_string_append_c (s, ')'); + + return g_string_free (s, FALSE); +} + +gchar * +script_fu_script_get_command_from_params (SFScript *script, + const GimpParam *params) +{ + GString *s; + gint i; + + g_return_val_if_fail (script != NULL, NULL); + + s = g_string_new ("("); + g_string_append (s, script->name); + + for (i = 0; i < script->n_args; i++) + { + const GimpParam *param = ¶ms[i + 1]; + + g_string_append_c (s, ' '); + + switch (script->args[i].type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + g_string_append_printf (s, "%d", param->data.d_int32); + break; + + case SF_COLOR: + { + guchar r, g, b; + + gimp_rgb_get_uchar (¶m->data.d_color, &r, &g, &b); + g_string_append_printf (s, "'(%d %d %d)", + (gint) r, (gint) g, (gint) b); + } + break; + + case SF_TOGGLE: + g_string_append_printf (s, (param->data.d_int32 ? "TRUE" : "FALSE")); + break; + + case SF_VALUE: + g_string_append (s, param->data.d_string); + break; + + case SF_STRING: + case SF_TEXT: + case SF_FILENAME: + case SF_DIRNAME: + { + gchar *tmp; + + tmp = script_fu_strescape (param->data.d_string); + g_string_append_printf (s, "\"%s\"", tmp); + g_free (tmp); + } + break; + + case SF_ADJUSTMENT: + { + gchar buffer[G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (buffer, sizeof (buffer), param->data.d_float); + g_string_append (s, buffer); + } + break; + + case SF_FONT: + case SF_PALETTE: + case SF_PATTERN: + case SF_GRADIENT: + case SF_BRUSH: + g_string_append_printf (s, "\"%s\"", param->data.d_string); + break; + + case SF_OPTION: + case SF_ENUM: + g_string_append_printf (s, "%d", param->data.d_int32); + break; + } + } + + g_string_append_c (s, ')'); + + return g_string_free (s, FALSE); +} + + +/* + * Local Functions + */ + +static gboolean +script_fu_script_param_init (SFScript *script, + gint nparams, + const GimpParam *params, + SFArgType type, + gint n) +{ + SFArg *arg = &script->args[n]; + + if (script->n_args > n && arg->type == type && nparams > n + 1) + { + switch (type) + { + case SF_IMAGE: + if (params[n + 1].type == GIMP_PDB_IMAGE) + { + arg->value.sfa_image = params[n + 1].data.d_image; + return TRUE; + } + break; + + case SF_DRAWABLE: + if (params[n + 1].type == GIMP_PDB_DRAWABLE) + { + arg->value.sfa_drawable = params[n + 1].data.d_drawable; + return TRUE; + } + break; + + case SF_LAYER: + if (params[n + 1].type == GIMP_PDB_LAYER) + { + arg->value.sfa_layer = params[n + 1].data.d_layer; + return TRUE; + } + break; + + case SF_CHANNEL: + if (params[n + 1].type == GIMP_PDB_CHANNEL) + { + arg->value.sfa_channel = params[n + 1].data.d_channel; + return TRUE; + } + break; + + case SF_VECTORS: + if (params[n + 1].type == GIMP_PDB_VECTORS) + { + arg->value.sfa_vectors = params[n + 1].data.d_vectors; + return TRUE; + } + break; + + case SF_DISPLAY: + if (params[n + 1].type == GIMP_PDB_DISPLAY) + { + arg->value.sfa_display = params[n + 1].data.d_display; + return TRUE; + } + break; + + default: + break; + } + } + + return FALSE; +} diff --git a/plug-ins/script-fu/script-fu-script.h b/plug-ins/script-fu/script-fu-script.h new file mode 100644 index 0000000..86b318f --- /dev/null +++ b/plug-ins/script-fu/script-fu-script.h @@ -0,0 +1,49 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_SCRIPT_H__ +#define __SCRIPT_FU_SCRIPT_H__ + + +SFScript * script_fu_script_new (const gchar *name, + const gchar *menu_label, + const gchar *blurb, + const gchar *author, + const gchar *copyright, + const gchar *date, + const gchar *image_types, + gint n_args); +void script_fu_script_free (SFScript *script); + +void script_fu_script_install_proc (SFScript *script, + GimpRunProc run_proc); +void script_fu_script_uninstall_proc (SFScript *script); + +gchar * script_fu_script_get_title (SFScript *script); +void script_fu_script_reset (SFScript *script, + gboolean reset_ids); + +gint script_fu_script_collect_standard_args (SFScript *script, + gint n_params, + const GimpParam *params); + +gchar * script_fu_script_get_command (SFScript *script); +gchar * script_fu_script_get_command_from_params (SFScript *script, + const GimpParam *params); + + +#endif /* __SCRIPT_FU_SCRIPT__ */ diff --git a/plug-ins/script-fu/script-fu-scripts.c b/plug-ins/script-fu/script-fu-scripts.c new file mode 100644 index 0000000..bf56edb --- /dev/null +++ b/plug-ins/script-fu/script-fu-scripts.c @@ -0,0 +1,934 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <glib.h> + +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "tinyscheme/scheme-private.h" + +#include "scheme-wrapper.h" + +#include "script-fu-types.h" + +#include "script-fu-interface.h" +#include "script-fu-script.h" +#include "script-fu-scripts.h" +#include "script-fu-utils.h" + +#include "script-fu-intl.h" + + +typedef struct +{ + SFScript *script; + gchar *menu_path; +} SFMenu; + + +/* + * Local Functions + */ + +static gboolean script_fu_run_command (const gchar *command, + GError **error); +static void script_fu_load_directory (GFile *directory); +static void script_fu_load_script (GFile *file); +static gboolean script_fu_install_script (gpointer foo, + GList *scripts, + gpointer bar); +static void script_fu_install_menu (SFMenu *menu); +static gboolean script_fu_remove_script (gpointer foo, + GList *scripts, + gpointer bar); +static void script_fu_script_proc (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); + +static SFScript *script_fu_find_script (const gchar *name); + +static gchar * script_fu_menu_map (const gchar *menu_path); +static gint script_fu_menu_compare (gconstpointer a, + gconstpointer b); + + +/* + * Local variables + */ + +static GTree *script_tree = NULL; +static GList *script_menu_list = NULL; + + +/* + * Function definitions + */ + +void +script_fu_find_scripts (GList *path) +{ + GList *list; + + /* Make sure to clear any existing scripts */ + if (script_tree != NULL) + { + g_tree_foreach (script_tree, + (GTraverseFunc) script_fu_remove_script, + NULL); + g_tree_destroy (script_tree); + } + + if (! path) + return; + + script_tree = g_tree_new ((GCompareFunc) g_utf8_collate); + + for (list = path; list; list = g_list_next (list)) + { + script_fu_load_directory (list->data); + } + + /* Now that all scripts are read in and sorted, tell gimp about them */ + g_tree_foreach (script_tree, + (GTraverseFunc) script_fu_install_script, + NULL); + + script_menu_list = g_list_sort (script_menu_list, + (GCompareFunc) script_fu_menu_compare); + + /* Install and nuke the list of menu entries */ + g_list_free_full (script_menu_list, + (GDestroyNotify) script_fu_install_menu); + script_menu_list = NULL; +} + +pointer +script_fu_add_script (scheme *sc, + pointer a) +{ + SFScript *script; + const gchar *name; + const gchar *menu_label; + const gchar *blurb; + const gchar *author; + const gchar *copyright; + const gchar *date; + const gchar *image_types; + gint n_args; + gint i; + + /* Check the length of a */ + if (sc->vptr->list_length (sc, a) < 7) + { + g_message (_("Too few arguments to 'script-fu-register' call")); + return sc->NIL; + } + + /* Find the script name */ + name = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + /* Find the script menu_label */ + menu_label = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + /* Find the script blurb */ + blurb = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + /* Find the script author */ + author = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + /* Find the script copyright */ + copyright = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + /* Find the script date */ + date = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + /* Find the script image types */ + if (sc->vptr->is_pair (a)) + { + image_types = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + } + else + { + image_types = sc->vptr->string_value (a); + a = sc->NIL; + } + + /* Check the supplied number of arguments */ + n_args = sc->vptr->list_length (sc, a) / 3; + + /* Create a new script */ + script = script_fu_script_new (name, + menu_label, + blurb, + author, + copyright, + date, + image_types, + n_args); + + for (i = 0; i < script->n_args; i++) + { + SFArg *arg = &script->args[i]; + + if (a != sc->NIL) + { + if (!sc->vptr->is_integer (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: argument types must be integer values", 0); + + arg->type = sc->vptr->ivalue (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + } + else + return foreign_error (sc, "script-fu-register: missing type specifier", 0); + + if (a != sc->NIL) + { + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: argument labels must be strings", 0); + + arg->label = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + a = sc->vptr->pair_cdr (a); + } + else + return foreign_error (sc, "script-fu-register: missing arguments label", 0); + + if (a != sc->NIL) + { + switch (arg->type) + { + case SF_IMAGE: + case SF_DRAWABLE: + case SF_LAYER: + case SF_CHANNEL: + case SF_VECTORS: + case SF_DISPLAY: + if (!sc->vptr->is_integer (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: default IDs must be integer values", 0); + + arg->default_value.sfa_image = + sc->vptr->ivalue (sc->vptr->pair_car (a)); + break; + + case SF_COLOR: + if (sc->vptr->is_string (sc->vptr->pair_car (a))) + { + if (! gimp_rgb_parse_css (&arg->default_value.sfa_color, + sc->vptr->string_value (sc->vptr->pair_car (a)), + -1)) + return foreign_error (sc, "script-fu-register: invalid default color name", 0); + + gimp_rgb_set_alpha (&arg->default_value.sfa_color, 1.0); + } + else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) && + sc->vptr->list_length(sc, sc->vptr->pair_car (a)) == 3) + { + pointer color_list; + guchar r, g, b; + + color_list = sc->vptr->pair_car (a); + r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255); + color_list = sc->vptr->pair_cdr (color_list); + g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255); + color_list = sc->vptr->pair_cdr (color_list); + b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255); + + gimp_rgb_set_uchar (&arg->default_value.sfa_color, r, g, b); + } + else + { + return foreign_error (sc, "script-fu-register: color defaults must be a list of 3 integers or a color name", 0); + } + break; + + case SF_TOGGLE: + if (!sc->vptr->is_integer (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: toggle default must be an integer value", 0); + + arg->default_value.sfa_toggle = + (sc->vptr->ivalue (sc->vptr->pair_car (a))) ? TRUE : FALSE; + break; + + case SF_VALUE: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: value defaults must be string values", 0); + + arg->default_value.sfa_value = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + break; + + case SF_STRING: + case SF_TEXT: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: string defaults must be string values", 0); + + arg->default_value.sfa_value = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + break; + + case SF_ADJUSTMENT: + { + pointer adj_list; + + if (!sc->vptr->is_list (sc, a)) + return foreign_error (sc, "script-fu-register: adjustment defaults must be a list", 0); + + adj_list = sc->vptr->pair_car (a); + arg->default_value.sfa_adjustment.value = + sc->vptr->rvalue (sc->vptr->pair_car (adj_list)); + + adj_list = sc->vptr->pair_cdr (adj_list); + arg->default_value.sfa_adjustment.lower = + sc->vptr->rvalue (sc->vptr->pair_car (adj_list)); + + adj_list = sc->vptr->pair_cdr (adj_list); + arg->default_value.sfa_adjustment.upper = + sc->vptr->rvalue (sc->vptr->pair_car (adj_list)); + + adj_list = sc->vptr->pair_cdr (adj_list); + arg->default_value.sfa_adjustment.step = + sc->vptr->rvalue (sc->vptr->pair_car (adj_list)); + + adj_list = sc->vptr->pair_cdr (adj_list); + arg->default_value.sfa_adjustment.page = + sc->vptr->rvalue (sc->vptr->pair_car (adj_list)); + + adj_list = sc->vptr->pair_cdr (adj_list); + arg->default_value.sfa_adjustment.digits = + sc->vptr->ivalue (sc->vptr->pair_car (adj_list)); + + adj_list = sc->vptr->pair_cdr (adj_list); + arg->default_value.sfa_adjustment.type = + sc->vptr->ivalue (sc->vptr->pair_car (adj_list)); + } + break; + + case SF_FILENAME: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: filename defaults must be string values", 0); + /* fallthrough */ + + case SF_DIRNAME: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: dirname defaults must be string values", 0); + + arg->default_value.sfa_file.filename = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + +#ifdef G_OS_WIN32 + { + /* Replace POSIX slashes with Win32 backslashes. This + * is just so script-fus can be written with only + * POSIX directory separators. + */ + gchar *filename = arg->default_value.sfa_file.filename; + + while (*filename) + { + if (*filename == '/') + *filename = G_DIR_SEPARATOR; + + filename++; + } + } +#endif + break; + + case SF_FONT: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: font defaults must be string values", 0); + + arg->default_value.sfa_font = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + break; + + case SF_PALETTE: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: palette defaults must be string values", 0); + + arg->default_value.sfa_palette = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + break; + + case SF_PATTERN: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: pattern defaults must be string values", 0); + + arg->default_value.sfa_pattern = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + break; + + case SF_BRUSH: + { + pointer brush_list; + + if (!sc->vptr->is_list (sc, a)) + return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0); + + brush_list = sc->vptr->pair_car (a); + arg->default_value.sfa_brush.name = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list))); + + brush_list = sc->vptr->pair_cdr (brush_list); + arg->default_value.sfa_brush.opacity = + sc->vptr->rvalue (sc->vptr->pair_car (brush_list)); + + brush_list = sc->vptr->pair_cdr (brush_list); + arg->default_value.sfa_brush.spacing = + sc->vptr->ivalue (sc->vptr->pair_car (brush_list)); + + brush_list = sc->vptr->pair_cdr (brush_list); + arg->default_value.sfa_brush.paint_mode = + sc->vptr->ivalue (sc->vptr->pair_car (brush_list)); + } + break; + + case SF_GRADIENT: + if (!sc->vptr->is_string (sc->vptr->pair_car (a))) + return foreign_error (sc, "script-fu-register: gradient defaults must be string values", 0); + + arg->default_value.sfa_gradient = + g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a))); + break; + + case SF_OPTION: + { + pointer option_list; + + if (!sc->vptr->is_list (sc, a)) + return foreign_error (sc, "script-fu-register: option defaults must be a list", 0); + + for (option_list = sc->vptr->pair_car (a); + option_list != sc->NIL; + option_list = sc->vptr->pair_cdr (option_list)) + { + arg->default_value.sfa_option.list = + g_slist_append (arg->default_value.sfa_option.list, + g_strdup (sc->vptr->string_value + (sc->vptr->pair_car (option_list)))); + } + } + break; + + case SF_ENUM: + { + pointer option_list; + const gchar *val; + gchar *type_name; + GEnumValue *enum_value; + GType enum_type; + + if (!sc->vptr->is_list (sc, a)) + return foreign_error (sc, "script-fu-register: enum defaults must be a list", 0); + + option_list = sc->vptr->pair_car (a); + if (!sc->vptr->is_string (sc->vptr->pair_car (option_list))) + return foreign_error (sc, "script-fu-register: first element in enum defaults must be a type-name", 0); + + val = sc->vptr->string_value (sc->vptr->pair_car (option_list)); + + if (g_str_has_prefix (val, "Gimp")) + type_name = g_strdup (val); + else + type_name = g_strconcat ("Gimp", val, NULL); + + enum_type = g_type_from_name (type_name); + if (! G_TYPE_IS_ENUM (enum_type)) + { + g_free (type_name); + return foreign_error (sc, "script-fu-register: first element in enum defaults must be the name of a registered type", 0); + } + + arg->default_value.sfa_enum.type_name = type_name; + + option_list = sc->vptr->pair_cdr (option_list); + if (!sc->vptr->is_string (sc->vptr->pair_car (option_list))) + return foreign_error (sc, "script-fu-register: second element in enum defaults must be a string", 0); + + enum_value = + g_enum_get_value_by_nick (g_type_class_peek (enum_type), + sc->vptr->string_value (sc->vptr->pair_car (option_list))); + if (enum_value) + arg->default_value.sfa_enum.history = enum_value->value; + } + break; + } + + a = sc->vptr->pair_cdr (a); + } + else + { + return foreign_error (sc, "script-fu-register: missing default argument", 0); + } + } + + /* fill all values from defaults */ + script_fu_script_reset (script, TRUE); + + if (script->menu_label[0] == '<') + { + gchar *mapped = script_fu_menu_map (script->menu_label); + + if (mapped) + { + g_free (script->menu_label); + script->menu_label = mapped; + } + } + + { + GList *list = g_tree_lookup (script_tree, script->menu_label); + + g_tree_insert (script_tree, (gpointer) script->menu_label, + g_list_append (list, script)); + } + + return sc->NIL; +} + +pointer +script_fu_add_menu (scheme *sc, + pointer a) +{ + SFScript *script; + SFMenu *menu; + const gchar *name; + const gchar *path; + + /* Check the length of a */ + if (sc->vptr->list_length (sc, a) != 2) + return foreign_error (sc, "Incorrect number of arguments for script-fu-menu-register", 0); + + /* Find the script PDB entry name */ + name = sc->vptr->string_value (sc->vptr->pair_car (a)); + a = sc->vptr->pair_cdr (a); + + script = script_fu_find_script (name); + + if (! script) + { + g_message ("Procedure %s in script-fu-menu-register does not exist", + name); + return sc->NIL; + } + + /* Create a new list of menus */ + menu = g_slice_new0 (SFMenu); + + menu->script = script; + + /* Find the script menu path */ + path = sc->vptr->string_value (sc->vptr->pair_car (a)); + + menu->menu_path = script_fu_menu_map (path); + + if (! menu->menu_path) + menu->menu_path = g_strdup (path); + + script_menu_list = g_list_prepend (script_menu_list, menu); + + return sc->NIL; +} + + +/* private functions */ + +static gboolean +script_fu_run_command (const gchar *command, + GError **error) +{ + GString *output; + gboolean success = FALSE; + + output = g_string_new (NULL); + ts_register_output_func (ts_gstring_output_func, output); + + if (ts_interpret_string (command)) + { + g_set_error (error, 0, 0, "%s", output->str); + } + else + { + success = TRUE; + } + + g_string_free (output, TRUE); + + return success; +} + +static void +script_fu_load_directory (GFile *directory) +{ + GFileEnumerator *enumerator; + + enumerator = g_file_enumerate_children (directory, + G_FILE_ATTRIBUTE_STANDARD_NAME "," + G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN "," + G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NONE, + NULL, NULL); + + if (enumerator) + { + GFileInfo *info; + + while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL))) + { + GFileType file_type = g_file_info_get_file_type (info); + + if ((file_type == G_FILE_TYPE_REGULAR || + file_type == G_FILE_TYPE_DIRECTORY) && + ! g_file_info_get_is_hidden (info)) + { + GFile *child = g_file_enumerator_get_child (enumerator, info); + + if (file_type == G_FILE_TYPE_DIRECTORY) + script_fu_load_directory (child); + else + script_fu_load_script (child); + + g_object_unref (child); + } + + g_object_unref (info); + } + + g_object_unref (enumerator); + } +} + +static void +script_fu_load_script (GFile *file) +{ + if (gimp_file_has_extension (file, ".scm")) + { + gchar *path = g_file_get_path (file); + gchar *escaped = script_fu_strescape (path); + gchar *command; + GError *error = NULL; + + command = g_strdup_printf ("(load \"%s\")", escaped); + g_free (escaped); + + if (! script_fu_run_command (command, &error)) + { + gchar *message = g_strdup_printf (_("Error while loading %s:"), + gimp_file_get_utf8_name (file)); + + g_message ("%s\n\n%s", message, error->message); + + g_clear_error (&error); + g_free (message); + } + +#ifdef G_OS_WIN32 + /* No, I don't know why, but this is + * necessary on NT 4.0. + */ + Sleep (0); +#endif + + g_free (command); + g_free (path); + } +} + +/* + * The following function is a GTraverseFunction. + */ +static gboolean +script_fu_install_script (gpointer foo G_GNUC_UNUSED, + GList *scripts, + gpointer bar G_GNUC_UNUSED) +{ + GList *list; + + for (list = scripts; list; list = g_list_next (list)) + { + SFScript *script = list->data; + + script_fu_script_install_proc (script, script_fu_script_proc); + } + + return FALSE; +} + +static void +script_fu_install_menu (SFMenu *menu) +{ + gimp_plugin_menu_register (menu->script->name, menu->menu_path); + + g_free (menu->menu_path); + g_slice_free (SFMenu, menu); +} + +/* + * The following function is a GTraverseFunction. + */ +static gboolean +script_fu_remove_script (gpointer foo G_GNUC_UNUSED, + GList *scripts, + gpointer bar G_GNUC_UNUSED) +{ + GList *list; + + for (list = scripts; list; list = g_list_next (list)) + { + SFScript *script = list->data; + + script_fu_script_uninstall_proc (script); + script_fu_script_free (script); + } + + g_list_free (scripts); + + return FALSE; +} + +static void +script_fu_script_proc (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[2] = { { 0, }, { 0, } }; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + SFScript *script; + GError *error = NULL; + + if (values[1].type == GIMP_PDB_STRING && values[1].data.d_string) + { + g_free (values[1].data.d_string); + values[1].data.d_string = NULL; + } + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + + script = script_fu_find_script (name); + + if (! script) + status = GIMP_PDB_CALLING_ERROR; + + if (status == GIMP_PDB_SUCCESS) + { + GimpRunMode run_mode = params[0].data.d_int32; + + ts_set_run_mode (run_mode); + + switch (run_mode) + { + case GIMP_RUN_INTERACTIVE: + { + gint min_args = 0; + + /* First, try to collect the standard script arguments... */ + min_args = script_fu_script_collect_standard_args (script, + nparams, params); + + /* ...then acquire the rest of arguments (if any) with a dialog */ + if (script->n_args > min_args) + { + status = script_fu_interface (script, min_args); + break; + } + /* otherwise (if the script takes no more arguments), skip + * this part and run the script directly (fallthrough) + */ + } + + case GIMP_RUN_NONINTERACTIVE: + /* Make sure all the arguments are there */ + if (nparams != (script->n_args + 1)) + status = GIMP_PDB_CALLING_ERROR; + + if (status == GIMP_PDB_SUCCESS) + { + gchar *command; + + command = script_fu_script_get_command_from_params (script, + params); + + /* run the command through the interpreter */ + if (! script_fu_run_command (command, &error)) + { + status = GIMP_PDB_EXECUTION_ERROR; + *nreturn_vals = 2; + values[1].type = GIMP_PDB_STRING; + values[1].data.d_string = error->message; + + error->message = NULL; + g_error_free (error); + } + + g_free (command); + } + break; + + case GIMP_RUN_WITH_LAST_VALS: + { + gchar *command; + + /* First, try to collect the standard script arguments */ + script_fu_script_collect_standard_args (script, nparams, params); + + command = script_fu_script_get_command (script); + + /* run the command through the interpreter */ + if (! script_fu_run_command (command, &error)) + { + status = GIMP_PDB_EXECUTION_ERROR; + *nreturn_vals = 2; + values[1].type = GIMP_PDB_STRING; + values[1].data.d_string = error->message; + + error->message = NULL; + g_error_free (error); + } + + g_free (command); + } + break; + + default: + break; + } + } + + values[0].data.d_status = status; +} + +/* this is a GTraverseFunction */ +static gboolean +script_fu_lookup_script (gpointer *foo G_GNUC_UNUSED, + GList *scripts, + gconstpointer *name) +{ + GList *list; + + for (list = scripts; list; list = g_list_next (list)) + { + SFScript *script = list->data; + + if (strcmp (script->name, *name) == 0) + { + /* store the script in the name pointer and stop the traversal */ + *name = script; + return TRUE; + } + } + + return FALSE; +} + +static SFScript * +script_fu_find_script (const gchar *name) +{ + gconstpointer script = name; + + g_tree_foreach (script_tree, + (GTraverseFunc) script_fu_lookup_script, + &script); + + if (script == name) + return NULL; + + return (SFScript *) script; +} + +static gchar * +script_fu_menu_map (const gchar *menu_path) +{ + /* for backward compatibility, we fiddle with some menu paths */ + const struct + { + const gchar *old; + const gchar *new; + } mapping[] = { + { "<Image>/Script-Fu/Alchemy", "<Image>/Filters/Artistic" }, + { "<Image>/Script-Fu/Alpha to Logo", "<Image>/Filters/Alpha to Logo" }, + { "<Image>/Script-Fu/Animators", "<Image>/Filters/Animation/Animators" }, + { "<Image>/Script-Fu/Decor", "<Image>/Filters/Decor" }, + { "<Image>/Script-Fu/Render", "<Image>/Filters/Render" }, + { "<Image>/Script-Fu/Selection", "<Image>/Select/Modify" }, + { "<Image>/Script-Fu/Shadow", "<Image>/Filters/Light and Shadow/Shadow" }, + { "<Image>/Script-Fu/Stencil Ops", "<Image>/Filters/Decor" } + }; + + gint i; + + for (i = 0; i < G_N_ELEMENTS (mapping); i++) + { + if (g_str_has_prefix (menu_path, mapping[i].old)) + { + const gchar *suffix = menu_path + strlen (mapping[i].old); + + if (*suffix != '/') + continue; + + return g_strconcat (mapping[i].new, suffix, NULL); + } + } + + return NULL; +} + +static gint +script_fu_menu_compare (gconstpointer a, + gconstpointer b) +{ + const SFMenu *menu_a = a; + const SFMenu *menu_b = b; + gint retval = 0; + + if (menu_a->menu_path && menu_b->menu_path) + { + retval = g_utf8_collate (menu_a->menu_path, + menu_b->menu_path); + + if (retval == 0 && + menu_a->script->menu_label && menu_b->script->menu_label) + { + retval = g_utf8_collate (menu_a->script->menu_label, + menu_b->script->menu_label); + } + } + + return retval; +} diff --git a/plug-ins/script-fu/script-fu-scripts.h b/plug-ins/script-fu/script-fu-scripts.h new file mode 100644 index 0000000..ef63870 --- /dev/null +++ b/plug-ins/script-fu/script-fu-scripts.h @@ -0,0 +1,29 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_SCRIPTS_H__ +#define __SCRIPT_FU_SCRIPTS_H__ + + +void script_fu_find_scripts (GList *path); +pointer script_fu_add_script (scheme *sc, + pointer a); +pointer script_fu_add_menu (scheme *sc, + pointer a); + + +#endif /* __SCRIPT_FU_SCRIPTS__ */ diff --git a/plug-ins/script-fu/script-fu-server.c b/plug-ins/script-fu/script-fu-server.c new file mode 100644 index 0000000..74270bf --- /dev/null +++ b/plug-ins/script-fu/script-fu-server.c @@ -0,0 +1,1113 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <time.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#include <sys/types.h> + +#include <glib.h> + +#ifdef G_OS_WIN32 +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0502 +#include <winsock2.h> +#include <ws2tcpip.h> + +typedef short sa_family_t; /* Not defined by winsock */ + +#ifndef AI_ADDRCONFIG +/* Missing from mingw headers, but value is publicly documented + * on http://msdn.microsoft.com/en-us/library/ms737530%28v=VS.85%29.aspx + */ +#define AI_ADDRCONFIG 0x0400 +#endif +#include <libgimpbase/gimpwin32-io.h> +#else +#include <sys/socket.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif /* HAVE_SYS_SELECT_H */ +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +#ifndef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0 +#endif +#endif + +#include <glib/gstdio.h> + +#include "libgimp/gimp.h" +#include "libgimp/gimpui.h" + +#include "script-fu-intl.h" + +#include "scheme-wrapper.h" +#include "script-fu-server.h" + +#ifdef G_OS_WIN32 +#define CLOSESOCKET(fd) closesocket(fd) +#else +#define CLOSESOCKET(fd) close(fd) +#endif + +#define COMMAND_HEADER 3 +#define RESPONSE_HEADER 4 +#define MAGIC 'G' + +#ifndef HAVE_DIFFTIME +#define difftime(a,b) (((gdouble)(a)) - ((gdouble)(b))) +#endif + +#ifndef NO_FD_SET +# define SELECT_MASK fd_set +#else +# ifndef _AIX + typedef long fd_mask; +# endif +# if defined(_IBMR2) +# define SELECT_MASK void +# else +# define SELECT_MASK int +# endif +#endif + + +/* image information */ + +/* Header format for incoming commands... + * bytes: 1 2 3 + * MAGIC CMD_LEN_H CMD_LEN_L + */ + +/* Header format for outgoing responses... + * bytes: 1 2 3 4 + * MAGIC ERROR? RSP_LEN_H RSP_LEN_L + */ + +#define MAGIC_BYTE 0 + +#define CMD_LEN_H_BYTE 1 +#define CMD_LEN_L_BYTE 2 + +#define ERROR_BYTE 1 +#define RSP_LEN_H_BYTE 2 +#define RSP_LEN_L_BYTE 3 + +/* + * Local Types + */ + +typedef struct +{ + gchar *command; + gint filedes; + gint request_no; +} SFCommand; + +typedef struct +{ + GtkWidget *ip_entry; + GtkWidget *port_entry; + GtkWidget *log_entry; + + gchar *listen_ip; + gint port; + gchar *logfile; + + gboolean run; +} ServerInterface; + +typedef union +{ + sa_family_t family; + struct sockaddr_storage ss; + struct sockaddr sa; + struct sockaddr_in sa_in; + struct sockaddr_in6 sa_in6; +} sa_union; + +/* + * Local Functions + */ + +static void server_start (const gchar *listen_ip, + gint port, + const gchar *logfile); +static gboolean execute_command (SFCommand *cmd); +static gint read_from_client (gint filedes); +static gint make_socket (const struct addrinfo + *ai); +static void server_log (const gchar *format, + ...) G_GNUC_PRINTF (1, 2); +static void server_quit (void); + +static gboolean server_interface (void); +static void response_callback (GtkWidget *widget, + gint response_id, + gpointer data); +static void print_socket_api_error (const gchar *api_name); + +/* + * Local variables + */ +static gint server_socks[2], + server_socks_used = 0; +static const gint server_socks_len = sizeof (server_socks) / + sizeof (server_socks[0]); +static GList *command_queue = NULL; +static gint queue_length = 0; +static gint request_no = 0; +static FILE *server_log_file = NULL; +static GHashTable *clients = NULL; +static gboolean script_fu_done = FALSE; +static gboolean server_mode = FALSE; + +static ServerInterface sint = +{ + NULL, /* port entry widget */ + NULL, /* log entry widget */ + NULL, /* ip entry widget */ + + NULL, /* ip to bind to */ + 10008, /* default port number */ + NULL, /* use stdout */ + + FALSE /* run */ +}; + +/* + * Server interface functions + */ + +void +script_fu_server_quit (void) +{ + script_fu_done = TRUE; +} + +gint +script_fu_server_get_mode (void) +{ + return server_mode; +} + +void +script_fu_server_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[1]; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GimpRunMode run_mode; + + run_mode = params[0].data.d_int32; + + ts_set_run_mode (run_mode); + ts_set_print_flag (1); + + switch (run_mode) + { + case GIMP_RUN_INTERACTIVE: + if (server_interface ()) + { + server_mode = TRUE; + + /* Start the server */ + server_start (sint.listen_ip, sint.port, sint.logfile); + } + break; + + case GIMP_RUN_NONINTERACTIVE: + /* Set server_mode to TRUE */ + server_mode = TRUE; + + /* Start the server */ + server_start ((params[1].data.d_string && + strlen (params[1].data.d_string)) ? + params[1].data.d_string : "127.0.0.1", + params[2].data.d_int32, + params[3].data.d_string); + break; + + case GIMP_RUN_WITH_LAST_VALS: + status = GIMP_PDB_CALLING_ERROR; + g_warning ("Script-Fu server does not handle \"GIMP_RUN_WITH_LAST_VALS\""); + + default: + break; + } + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = status; +} + +static void +script_fu_server_add_fd (gpointer key, + gpointer value, + gpointer data) +{ + FD_SET (GPOINTER_TO_INT (key), (SELECT_MASK *) data); +} + +static gboolean +script_fu_server_read_fd (gpointer key, + gpointer value, + gpointer data) +{ + gint fd = GPOINTER_TO_INT (key); + + if (FD_ISSET (fd, (SELECT_MASK *) data)) + { + if (read_from_client (fd) < 0) + { + GList *list; + + server_log ("Server: disconnect from host %s.\n", (gchar *) value); + + CLOSESOCKET (fd); + + /* Invalidate the file descriptor for pending commands + from the disconnected client. */ + for (list = command_queue; list; list = list->next) + { + SFCommand *cmd = (SFCommand *) command_queue->data; + + if (cmd->filedes == fd) + cmd->filedes = -1; + } + + return TRUE; /* remove this client from the hash table */ + } + } + + return FALSE; +} + +void +script_fu_server_listen (gint timeout) +{ + struct timeval tv; + struct timeval *tvp = NULL; + SELECT_MASK fds; + gint sockno; + + /* Set time struct */ + if (timeout) + { + tv.tv_sec = timeout / 1000; + tv.tv_usec = timeout % 1000; + tvp = &tv; + } + + FD_ZERO (&fds); + for (sockno = 0; sockno < server_socks_used; sockno++) + { + FD_SET (server_socks[sockno], &fds); + } + g_hash_table_foreach (clients, script_fu_server_add_fd, &fds); + + /* Block until input arrives on one or more active sockets + or timeout occurs. */ + + if (select (FD_SETSIZE, &fds, NULL, NULL, tvp) < 0) + { + print_socket_api_error ("select"); + return; + } + + /* Service the server sockets if any has input pending. */ + for (sockno = 0; sockno < server_socks_used; sockno++) + { + sa_union client; + gchar clientname[NI_MAXHOST]; + + /* Connection request on original socket. */ + socklen_t size = sizeof (client); + gint new; + guint portno; + + if (! FD_ISSET (server_socks[sockno], &fds)) + { + continue; + } + + new = accept (server_socks[sockno], &(client.sa), &size); + + if (new < 0) + { + print_socket_api_error ("accept"); + return; + } + + /* Associate the client address with the socket */ + + /* If all else fails ... */ + strncpy (clientname, "(error during host address lookup)", NI_MAXHOST-1); + + /* Lookup address */ + (void) getnameinfo (&(client.sa), size, clientname, sizeof (clientname), + NULL, 0, NI_NUMERICHOST); + + g_hash_table_insert (clients, GINT_TO_POINTER (new), + g_strdup (clientname)); + + /* Determine port number */ + switch (client.family) + { + case AF_INET: + portno = (guint) g_ntohs (client.sa_in.sin_port); + break; + case AF_INET6: + portno = (guint) g_ntohs (client.sa_in6.sin6_port); + break; + default: + portno = 0; + } + + server_log ("Server: connect from host %s, port %d.\n", + clientname, portno); + } + + /* Service the client sockets. */ + g_hash_table_foreach_remove (clients, script_fu_server_read_fd, &fds); +} + +static void +server_progress_start (const gchar *message, + gboolean cancelable, + gpointer user_data) +{ + /* do nothing */ +} + +static void +server_progress_end (gpointer user_data) +{ + /* do nothing */ +} + +static void +server_progress_set_text (const gchar *message, + gpointer user_data) +{ + /* do nothing */ +} + +static void +server_progress_set_value (gdouble percentage, + gpointer user_data) +{ + /* do nothing */ +} + + +/* + * Suppress progress popups by installing progress handlers that do nothing. + */ +static const gchar * +server_progress_install (void) +{ + GimpProgressVtable vtable = { 0, }; + + vtable.start = server_progress_start; + vtable.end = server_progress_end; + vtable.set_text = server_progress_set_text; + vtable.set_value = server_progress_set_value; + + return gimp_progress_install_vtable (&vtable, NULL); +} + +static void +server_progress_uninstall (const gchar *progress) +{ + gimp_progress_uninstall (progress); +} + +static void +server_start (const gchar *listen_ip, + gint port, + const gchar *logfile) +{ + struct addrinfo *ai; + struct addrinfo *ai_curr; + struct addrinfo hints; + gint e; + gint sockno; + gchar *port_s; + const gchar *progress; + + memset (&hints, 0, sizeof (hints)); + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + + port_s = g_strdup_printf ("%d", port); + e = getaddrinfo (listen_ip, port_s, &hints, &ai); + g_free (port_s); + + if (e != 0) + { + g_printerr ("getaddrinfo: %s\n", gai_strerror (e)); + return; + } + + for (ai_curr = ai, sockno = 0; + ai_curr != NULL && sockno < server_socks_len; + ai_curr = ai_curr->ai_next, sockno++) + { + /* Create the socket and set it up to accept connections. */ + /* This may fail if there's a server running on this port already. */ + server_socks[sockno] = make_socket (ai_curr); + + if (listen (server_socks[sockno], 5) < 0) + { + print_socket_api_error ("listen"); + freeaddrinfo (ai); + return; + } + } + + server_socks_used = sockno; + + /* Setup up the server log file */ + if (logfile && *logfile) + server_log_file = g_fopen (logfile, "a"); + else + server_log_file = NULL; + + if (! server_log_file) + server_log_file = stdout; + + /* Set up the clientname hash table */ + clients = g_hash_table_new_full (g_direct_hash, NULL, + NULL, (GDestroyNotify) g_free); + + progress = server_progress_install (); + + server_log ("Script-Fu server initialized and listening...\n"); + + /* Loop until the server is finished */ + while (! script_fu_done) + { + script_fu_server_listen (0); + + while (command_queue) + { + SFCommand *cmd = (SFCommand *) command_queue->data; + + /* Process the command */ + execute_command (cmd); + + /* Remove the command from the list */ + command_queue = g_list_remove (command_queue, cmd); + queue_length--; + + /* Free the request */ + g_free (cmd->command); + g_free (cmd); + } + } + + server_progress_uninstall (progress); + + freeaddrinfo (ai); + server_quit (); +} + +static gboolean +execute_command (SFCommand *cmd) +{ + guchar buffer[RESPONSE_HEADER]; + GString *response; + time_t clocknow; + gboolean error; + gint i; + gdouble total_time; + GTimer *timer; + + server_log ("Processing request #%d\n", cmd->request_no); + timer = g_timer_new (); + + response = g_string_new (NULL); + ts_register_output_func (ts_gstring_output_func, response); + + /* run the command */ + if (ts_interpret_string (cmd->command) != 0) + { + error = TRUE; + + server_log ("%s\n", response->str); + } + else + { + error = FALSE; + + if (response->len == 0) + g_string_assign (response, ts_get_success_msg ()); + + total_time = g_timer_elapsed (timer, NULL); + time (&clocknow); + server_log ("Request #%d processed in %.3f seconds, finishing on %s", + cmd->request_no, total_time, ctime (&clocknow)); + } + g_timer_destroy (timer); + + buffer[MAGIC_BYTE] = MAGIC; + buffer[ERROR_BYTE] = error ? TRUE : FALSE; + buffer[RSP_LEN_H_BYTE] = (guchar) (response->len >> 8); + buffer[RSP_LEN_L_BYTE] = (guchar) (response->len & 0xFF); + + /* Write the response to the client */ + for (i = 0; i < RESPONSE_HEADER; i++) + if (cmd->filedes > 0 && send (cmd->filedes, (const void *) (buffer + i), 1, 0) < 0) + { + /* Write error */ + print_socket_api_error ("send"); + return FALSE; + } + + for (i = 0; i < response->len; i++) + if (cmd->filedes > 0 && send (cmd->filedes, response->str + i, 1, 0) < 0) + { + /* Write error */ + print_socket_api_error ("send"); + return FALSE; + } + + g_string_free (response, TRUE); + + return FALSE; +} + +static gint +read_from_client (gint filedes) +{ + SFCommand *cmd; + guchar buffer[COMMAND_HEADER]; + gchar *command; + gchar *clientaddr; + time_t clock; + gint command_len; + gint nbytes; + gint i; + + for (i = 0; i < COMMAND_HEADER;) + { + nbytes = recv (filedes, (void *) (buffer + i), COMMAND_HEADER - i, 0); + + if (nbytes < 0) + { +#ifndef G_OS_WIN32 + if (errno == EINTR) + continue; +#endif + server_log ("Error reading command header.\n"); + return -1; + } + + if (nbytes == 0) + return -1; /* EOF */ + + i += nbytes; + } + + if (buffer[MAGIC_BYTE] != MAGIC) + { + server_log ("Error in script-fu command transmission.\n"); + return -1; + } + + command_len = (buffer [CMD_LEN_H_BYTE] << 8) | buffer [CMD_LEN_L_BYTE]; + command = g_new (gchar, command_len + 1); + + for (i = 0; i < command_len;) + { + nbytes = recv (filedes, command + i, command_len - i, 0); + + if (nbytes <= 0) + { +#ifndef G_OS_WIN32 + if (nbytes < 0 && errno == EINTR) + continue; +#endif + server_log ("Error reading command. Read %d out of %d bytes.\n", + i, command_len); + g_free (command); + return -1; + } + + i += nbytes; + } + + command[command_len] = '\0'; + cmd = g_new (SFCommand, 1); + + cmd->filedes = filedes; + cmd->command = command; + cmd->request_no = request_no ++; + + /* Add the command to the queue */ + command_queue = g_list_append (command_queue, cmd); + queue_length ++; + + /* Get the client address from the address/socket table */ + clientaddr = g_hash_table_lookup (clients, GINT_TO_POINTER (cmd->filedes)); + time (&clock); + server_log ("Received request #%d from IP address %s: %s on %s," + "[Request queue length: %d]", + cmd->request_no, + clientaddr ? clientaddr : "<invalid>", + cmd->command, ctime (&clock), queue_length); + + return 0; +} + +static gint +make_socket (const struct addrinfo *ai) +{ + gint sock; + gint v = 1; + + /* Win32 needs the winsock library initialized. */ +#ifdef G_OS_WIN32 + static gboolean winsock_initialized = FALSE; + + if (! winsock_initialized) + { + WORD wVersionRequested = MAKEWORD (2, 2); + WSADATA wsaData; + + if (WSAStartup (wVersionRequested, &wsaData) == 0) + { + winsock_initialized = TRUE; + } + else + { + print_socket_api_error ("WSAStartup"); + gimp_quit (); + } + } +#endif + + /* Create the socket. */ + sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) + { + print_socket_api_error ("socket"); + gimp_quit (); + } + + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &v, sizeof(v)); + +#ifdef IPV6_V6ONLY + /* Only listen on IPv6 addresses, otherwise bind() will fail. */ + if (ai->ai_family == AF_INET6) + { + v = 1; + if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &v, sizeof(v)) < 0) + { + print_socket_api_error ("setsockopt"); + gimp_quit(); + } + } +#endif + + if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0) + { + print_socket_api_error ("bind"); + gimp_quit (); + } + + return sock; +} + +static void +server_log (const gchar *format, + ...) +{ + va_list args; + gchar *buf; + + va_start (args, format); + buf = g_strdup_vprintf (format, args); + va_end (args); + + fputs (buf, server_log_file); + g_free (buf); + + if (server_log_file != stdout) + fflush (server_log_file); +} + +static void +script_fu_server_shutdown_fd (gpointer key, + gpointer value, + gpointer data) +{ + shutdown (GPOINTER_TO_INT (key), 2); +} + +static void +server_quit (void) +{ + gint sockno; + + for (sockno = 0; sockno < server_socks_used; sockno++) + { + CLOSESOCKET (server_socks[sockno]); + } + + if (clients) + { + g_hash_table_foreach (clients, script_fu_server_shutdown_fd, NULL); + g_hash_table_destroy (clients); + clients = NULL; + } + + while (command_queue) + { + SFCommand *cmd = command_queue->data; + + g_free (cmd->command); + g_free (cmd); + } + + g_list_free (command_queue); + command_queue = NULL; + queue_length = 0; + + /* Close the server log file */ + if (server_log_file != stdout) + fclose (server_log_file); + + server_log_file = NULL; +} + +static gboolean +server_interface (void) +{ + GtkWidget *dlg; + GtkWidget *main_vbox; + GtkWidget *table; + GtkWidget *hbox; + GtkWidget *image; + GtkWidget *label; + + INIT_I18N(); + + gimp_ui_init ("script-fu", FALSE); + + dlg = gimp_dialog_new (_("Script-Fu Server Options"), "gimp-script-fu", + NULL, 0, + gimp_standard_help_func, "plug-in-script-fu-server", + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Start Server"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (dlg), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + g_signal_connect (dlg, "response", + G_CALLBACK (response_callback), + NULL); + g_signal_connect (dlg, "destroy", + G_CALLBACK (gtk_main_quit), + NULL); + + main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), + main_vbox, TRUE, TRUE, 0); + gtk_widget_show (main_vbox); + + /* The table to hold port, logfile and listen-to entries */ + table = gtk_table_new (3, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + /* The server ip to listen to */ + sint.ip_entry = gtk_entry_new (); + gtk_entry_set_text (GTK_ENTRY (sint.ip_entry), "127.0.0.1"); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("Listen on IP:"), 0.0, 0.5, + sint.ip_entry, 1, FALSE); + + /* The server port */ + sint.port_entry = gtk_entry_new (); + gtk_entry_set_text (GTK_ENTRY (sint.port_entry), "10008"); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Server port:"), 0.0, 0.5, + sint.port_entry, 1, FALSE); + + /* The server logfile */ + sint.log_entry = gtk_entry_new (); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, + _("Server logfile:"), 0.0, 0.5, + sint.log_entry, 1, FALSE); + + /* Warning */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + image = gtk_image_new_from_icon_name (GIMP_ICON_DIALOG_WARNING, + GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0); + gtk_widget_show (image); + + label = gtk_label_new (_("Listening on an IP address other than " + "127.0.0.1 (especially 0.0.0.0) can allow " + "attackers to remotely execute arbitrary code " + "on this machine.")); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gimp_label_set_attributes (GTK_LABEL (label), + PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, + -1); + gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); + gtk_widget_show (label); + + gtk_widget_show (dlg); + + gtk_main (); + + return sint.run; +} + +static void +response_callback (GtkWidget *widget, + gint response_id, + gpointer data) +{ + if (response_id == GTK_RESPONSE_OK) + { + g_free (sint.logfile); + g_free (sint.listen_ip); + + sint.port = atoi (gtk_entry_get_text (GTK_ENTRY (sint.port_entry))); + sint.logfile = g_strdup (gtk_entry_get_text (GTK_ENTRY (sint.log_entry))); + sint.listen_ip = g_strdup (gtk_entry_get_text (GTK_ENTRY (sint.ip_entry))); + sint.run = TRUE; + } + + gtk_widget_destroy (widget); +} + +static void +print_socket_api_error (const gchar *api_name) +{ +#ifdef G_OS_WIN32 + /* Yes, this functionality really belongs to GLib. */ + const gchar *emsg; + gchar unk[100]; + int number = WSAGetLastError (); + + switch (number) + { + case WSAEINTR: + emsg = "Interrupted function call"; + break; + case WSAEACCES: + emsg = "Permission denied"; + break; + case WSAEFAULT: + emsg = "Bad address"; + break; + case WSAEINVAL: + emsg = "Invalid argument"; + break; + case WSAEMFILE: + emsg = "Too many open sockets"; + break; + case WSAEWOULDBLOCK: + emsg = "Resource temporarily unavailable"; + break; + case WSAEINPROGRESS: + emsg = "Operation now in progress"; + break; + case WSAEALREADY: + emsg = "Operation already in progress"; + break; + case WSAENOTSOCK: + emsg = "Socket operation on nonsocket"; + break; + case WSAEDESTADDRREQ: + emsg = "Destination address required"; + break; + case WSAEMSGSIZE: + emsg = "Message too long"; + break; + case WSAEPROTOTYPE: + emsg = "Protocol wrong type for socket"; + break; + case WSAENOPROTOOPT: + emsg = "Bad protocol option"; + break; + case WSAEPROTONOSUPPORT: + emsg = "Protocol not supported"; + break; + case WSAESOCKTNOSUPPORT: + emsg = "Socket type not supported"; + break; + case WSAEOPNOTSUPP: + emsg = "Operation not supported on transport endpoint"; + break; + case WSAEPFNOSUPPORT: + emsg = "Protocol family not supported"; + break; + case WSAEAFNOSUPPORT: + emsg = "Address family not supported by protocol family"; + break; + case WSAEADDRINUSE: + emsg = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + emsg = "Address not available"; + break; + case WSAENETDOWN: + emsg = "Network interface is not configured"; + break; + case WSAENETUNREACH: + emsg = "Network is unreachable"; + break; + case WSAENETRESET: + emsg = "Network dropped connection on reset"; + break; + case WSAECONNABORTED: + emsg = "Software caused connection abort"; + break; + case WSAECONNRESET: + emsg = "Connection reset by peer"; + break; + case WSAENOBUFS: + emsg = "No buffer space available"; + break; + case WSAEISCONN: + emsg = "Socket is already connected"; + break; + case WSAENOTCONN: + emsg = "Socket is not connected"; + break; + case WSAESHUTDOWN: + emsg = "Can't send after socket shutdown"; + break; + case WSAETIMEDOUT: + emsg = "Connection timed out"; + break; + case WSAECONNREFUSED: + emsg = "Connection refused"; + break; + case WSAEHOSTDOWN: + emsg = "Host is down"; + break; + case WSAEHOSTUNREACH: + emsg = "Host is unreachable"; + break; + case WSAEPROCLIM: + emsg = "Too many processes"; + break; + case WSASYSNOTREADY: + emsg = "Network subsystem is unavailable"; + break; + case WSAVERNOTSUPPORTED: + emsg = "Winsock.dll version out of range"; + break; + case WSANOTINITIALISED: + emsg = "Successful WSAStartup not yet performed"; + break; + case WSAEDISCON: + emsg = "Graceful shutdown in progress"; + break; + case WSATYPE_NOT_FOUND: + emsg = "Class type not found"; + break; + case WSAHOST_NOT_FOUND: + emsg = "Host not found"; + break; + case WSATRY_AGAIN: + emsg = "Nonauthoritative host not found"; + break; + case WSANO_RECOVERY: + emsg = "This is a nonrecoverable error"; + break; + case WSANO_DATA: + emsg = "Valid name, no data record of requested type"; + break; + case WSA_INVALID_HANDLE: + emsg = "Specified event object handle is invalid"; + break; + case WSA_INVALID_PARAMETER: + emsg = "One or more parameters are invalid"; + break; + case WSA_IO_INCOMPLETE: + emsg = "Overlapped I/O event object not in signaled state"; + break; + case WSA_NOT_ENOUGH_MEMORY: + emsg = "Insufficient memory available"; + break; + case WSA_OPERATION_ABORTED: + emsg = "Overlapped operation aborted"; + break; + case WSAEINVALIDPROCTABLE: + emsg = "Invalid procedure table from service provider"; + break; + case WSAEINVALIDPROVIDER: + emsg = "Invalid service provider version number"; + break; + case WSAEPROVIDERFAILEDINIT: + emsg = "Unable to initialize a service provider"; + break; + case WSASYSCALLFAILURE: + emsg = "System call failure"; + break; + default: + sprintf (unk, "Unknown WinSock error %d", number); + emsg = unk; + break; + } + + g_printerr ("%s failed: %s\n", api_name, emsg); +#else + perror (api_name); +#endif +} diff --git a/plug-ins/script-fu/script-fu-server.h b/plug-ins/script-fu/script-fu-server.h new file mode 100644 index 0000000..96b88ee --- /dev/null +++ b/plug-ins/script-fu/script-fu-server.h @@ -0,0 +1,32 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_SERVER_H__ +#define __SCRIPT_FU_SERVER_H__ + + +void script_fu_server_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); +void script_fu_server_listen (gint timeout); +gint script_fu_server_get_mode (void); +void script_fu_server_quit (void); + + +#endif /* __SCRIPT_FU_SERVER__ */ diff --git a/plug-ins/script-fu/script-fu-text-console.c b/plug-ins/script-fu/script-fu-text-console.c new file mode 100644 index 0000000..94c8d7c --- /dev/null +++ b/plug-ins/script-fu/script-fu-text-console.c @@ -0,0 +1,60 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdio.h> +#include <errno.h> + +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "libgimp/gimp.h" + +#include "scheme-wrapper.h" +#include "script-fu-text-console.h" + +#include "script-fu-intl.h" + +void +script_fu_text_console_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[1]; + + /* Enable Script-Fu output */ + ts_register_output_func (ts_stdout_output_func, NULL); + + ts_print_welcome (); + + gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_PLUGIN); + + /* Run the interface */ + ts_interpret_stdin (); + + gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_INTERNAL); + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_SUCCESS; + + *nreturn_vals = 1; + *return_vals = values; +} diff --git a/plug-ins/script-fu/script-fu-text-console.h b/plug-ins/script-fu/script-fu-text-console.h new file mode 100644 index 0000000..83c9860 --- /dev/null +++ b/plug-ins/script-fu/script-fu-text-console.h @@ -0,0 +1,29 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_TEXT_CONSOLE_H__ +#define __SCRIPT_FU_TEXT_CONSOLE_H__ + + +void script_fu_text_console_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); + + +#endif /* __SCRIPT_FU_TEXT_CONSOLE_H__ */ diff --git a/plug-ins/script-fu/script-fu-types.h b/plug-ins/script-fu/script-fu-types.h new file mode 100644 index 0000000..f0231b5 --- /dev/null +++ b/plug-ins/script-fu/script-fu-types.h @@ -0,0 +1,107 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_TYPES_H__ +#define __SCRIPT_FU_TYPES_H__ + + +#include "script-fu-enums.h" + + +typedef struct +{ + GtkAdjustment *adj; + gdouble value; + gdouble lower; + gdouble upper; + gdouble step; + gdouble page; + gint digits; + SFAdjustmentType type; +} SFAdjustment; + +typedef struct +{ + gchar *filename; +} SFFilename; + +typedef struct +{ + gchar *name; + gdouble opacity; + gint spacing; + GimpLayerMode paint_mode; +} SFBrush; + +typedef struct +{ + GSList *list; + gint history; +} SFOption; + +typedef struct +{ + gchar *type_name; + gint history; +} SFEnum; + +typedef union +{ + gint32 sfa_image; + gint32 sfa_drawable; + gint32 sfa_layer; + gint32 sfa_channel; + gint32 sfa_vectors; + gint32 sfa_display; + GimpRGB sfa_color; + gint32 sfa_toggle; + gchar *sfa_value; + SFAdjustment sfa_adjustment; + SFFilename sfa_file; + gchar *sfa_font; + gchar *sfa_gradient; + gchar *sfa_palette; + gchar *sfa_pattern; + SFBrush sfa_brush; + SFOption sfa_option; + SFEnum sfa_enum; +} SFArgValue; + +typedef struct +{ + SFArgType type; + gchar *label; + SFArgValue default_value; + SFArgValue value; +} SFArg; + +typedef struct +{ + gchar *name; + gchar *menu_label; + gchar *blurb; + gchar *author; + gchar *copyright; + gchar *date; + gchar *image_types; + + gint n_args; + SFArg *args; +} SFScript; + + +#endif /* __SCRIPT_FU_TYPES__ */ diff --git a/plug-ins/script-fu/script-fu-utils.c b/plug-ins/script-fu/script-fu-utils.c new file mode 100644 index 0000000..3e068cc --- /dev/null +++ b/plug-ins/script-fu/script-fu-utils.c @@ -0,0 +1,69 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <glib.h> + +#include "script-fu-utils.h" + + +/* + * Escapes the special characters '\b', '\f', '\n', '\r', '\t', '\' and '"' + * in the string source by inserting a '\' before them. + */ +gchar * +script_fu_strescape (const gchar *source) +{ + const guchar *p; + gchar *dest; + gchar *q; + + g_return_val_if_fail (source != NULL, NULL); + + p = (const guchar *) source; + + /* Each source byte needs maximally two destination chars */ + q = dest = g_malloc (strlen (source) * 2 + 1); + + while (*p) + { + switch (*p) + { + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + case '\\': + case '"': + *q++ = '\\'; + /* fallthrough */ + default: + *q++ = *p; + break; + } + + p++; + } + + *q = 0; + + return dest; +} diff --git a/plug-ins/script-fu/script-fu-utils.h b/plug-ins/script-fu/script-fu-utils.h new file mode 100644 index 0000000..a62a226 --- /dev/null +++ b/plug-ins/script-fu/script-fu-utils.h @@ -0,0 +1,25 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __SCRIPT_FU_UTILS_H__ +#define __SCRIPT_FU_UTILS_H__ + + +gchar * script_fu_strescape (const gchar *source); + + +#endif /* __SCRIPT_FU_UTILS__ */ diff --git a/plug-ins/script-fu/script-fu.c b/plug-ins/script-fu/script-fu.c new file mode 100644 index 0000000..558e15a --- /dev/null +++ b/plug-ins/script-fu/script-fu.c @@ -0,0 +1,385 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "tinyscheme/scheme.h" + +#include "script-fu-types.h" + +#include "script-fu-console.h" +#include "script-fu-eval.h" +#include "script-fu-interface.h" +#include "script-fu-scripts.h" +#include "script-fu-server.h" +#include "script-fu-text-console.h" + +#include "scheme-wrapper.h" + +#include "script-fu-intl.h" + + +/* Declare local functions. */ + +static void script_fu_query (void); +static void script_fu_run (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); +static GList * script_fu_search_path (void); +static void script_fu_extension_init (void); +static void script_fu_refresh_proc (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals); + + +const GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + script_fu_query, /* query_proc */ + script_fu_run /* run_proc */ +}; + + +MAIN () + + +static void +script_fu_query (void) +{ + static const GimpParamDef console_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0) }" } + }; + + static const GimpParamDef textconsole_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0) }" } + }; + + static const GimpParamDef eval_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_STRING, "code", "The code to evaluate" } + }; + + static const GimpParamDef server_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_STRING, "ip", "The ip on which to listen for requests" }, + { GIMP_PDB_INT32, "port", "The port on which to listen for requests" }, + { GIMP_PDB_STRING, "logfile", "The file to log server activity to" } + }; + + gimp_plugin_domain_register (GETTEXT_PACKAGE "-script-fu", NULL); + + gimp_install_procedure ("extension-script-fu", + "A scheme interpreter for scripting GIMP operations", + "More help here later", + "Spencer Kimball & Peter Mattis", + "Spencer Kimball & Peter Mattis", + "1997", + NULL, + NULL, + GIMP_EXTENSION, + 0, 0, NULL, NULL); + + gimp_install_procedure ("plug-in-script-fu-console", + N_("Interactive console for Script-Fu development"), + "Provides an interface which allows interactive " + "scheme development.", + "Spencer Kimball & Peter Mattis", + "Spencer Kimball & Peter Mattis", + "1997", + N_("_Console"), + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (console_args), 0, + console_args, NULL); + + gimp_plugin_menu_register ("plug-in-script-fu-console", + "<Image>/Filters/Languages/Script-Fu"); + + gimp_install_procedure ("plug-in-script-fu-text-console", + "Provides a text console mode for script-fu " + "development", + "Provides an interface which allows interactive " + "scheme development.", + "Spencer Kimball & Peter Mattis", + "Spencer Kimball & Peter Mattis", + "1997", + NULL, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (textconsole_args), 0, + textconsole_args, NULL); + + gimp_install_procedure ("plug-in-script-fu-server", + N_("Server for remote Script-Fu operation"), + "Provides a server for remote script-fu operation. " + "NOTE that for security reasons this procedure's " + "API was changed in an incompatible way since " + "GIMP 2.8.12. You now have to pass the IP to listen " + "on as first parameter. Calling this procedure with " + "the old API will fail on purpose.", + "Spencer Kimball & Peter Mattis", + "Spencer Kimball & Peter Mattis", + "1997", + N_("_Start Server..."), + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (server_args), 0, + server_args, NULL); + + gimp_plugin_menu_register ("plug-in-script-fu-server", + "<Image>/Filters/Languages/Script-Fu"); + + gimp_install_procedure ("plug-in-script-fu-eval", + "Evaluate scheme code", + "Evaluate the code under the scheme interpreter " + "(primarily for batch mode)", + "Manish Singh", + "Manish Singh", + "1998", + NULL, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (eval_args), 0, + eval_args, NULL); +} + +static void +script_fu_run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + GList *path; + + INIT_I18N(); + + path = script_fu_search_path (); + + /* Determine before we allow scripts to register themselves + * whether this is the base, automatically installed script-fu extension + */ + if (strcmp (name, "extension-script-fu") == 0) + { + /* Setup auxiliary temporary procedures for the base extension */ + script_fu_extension_init (); + + /* Init the interpreter and register scripts */ + tinyscheme_init (path, TRUE); + } + else + { + /* Init the interpreter */ + tinyscheme_init (path, FALSE); + } + + if (param != NULL) + ts_set_run_mode ((GimpRunMode) param[0].data.d_int32); + + /* Load all of the available scripts */ + script_fu_find_scripts (path); + + g_list_free_full (path, (GDestroyNotify) g_object_unref); + + if (strcmp (name, "extension-script-fu") == 0) + { + /* + * The main script-fu extension. + */ + + static GimpParam values[1]; + + /* Acknowledge that the extension is properly initialized */ + gimp_extension_ack (); + + /* Go into an endless loop */ + while (TRUE) + gimp_extension_process (0); + + /* Set return values; pointless because we never get out of the loop */ + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_SUCCESS; + } + else if (strcmp (name, "plug-in-script-fu-text-console") == 0) + { + /* + * The script-fu text console for interactive Scheme development + */ + + script_fu_text_console_run (name, nparams, param, + nreturn_vals, return_vals); + } + else if (strcmp (name, "plug-in-script-fu-console") == 0) + { + /* + * The script-fu console for interactive Scheme development + */ + + script_fu_console_run (name, nparams, param, + nreturn_vals, return_vals); + } + else if (strcmp (name, "plug-in-script-fu-server") == 0) + { + /* + * The script-fu server for remote operation + */ + + script_fu_server_run (name, nparams, param, + nreturn_vals, return_vals); + } + else if (strcmp (name, "plug-in-script-fu-eval") == 0) + { + /* + * A non-interactive "console" (for batch mode) + */ + + script_fu_eval_run (name, nparams, param, + nreturn_vals, return_vals); + } +} + +static GList * +script_fu_search_path (void) +{ + gchar *path_str; + GList *path = NULL; + + path_str = gimp_gimprc_query ("script-fu-path"); + + if (path_str) + { + GError *error = NULL; + + path = gimp_config_path_expand_to_files (path_str, &error); + g_free (path_str); + + if (! path) + { + g_warning ("Can't convert script-fu-path to filesystem encoding: %s", + error->message); + g_clear_error (&error); + } + } + + return path; +} + +static void +script_fu_extension_init (void) +{ + static const GimpParamDef args[] = + { + { GIMP_PDB_INT32, "run-mode", "[Interactive], non-interactive" } + }; + + gimp_plugin_menu_branch_register ("<Image>/Help", N_("_GIMP Online")); + gimp_plugin_menu_branch_register ("<Image>/Help", N_("_User Manual")); + + gimp_plugin_menu_branch_register ("<Image>/Filters/Languages", + N_("_Script-Fu")); + gimp_plugin_menu_branch_register ("<Image>/Filters/Languages/Script-Fu", + N_("_Test")); + + gimp_plugin_menu_branch_register ("<Image>/File/Create", + N_("_Buttons")); + gimp_plugin_menu_branch_register ("<Image>/File/Create", + N_("_Logos")); + gimp_plugin_menu_branch_register ("<Image>/File/Create", + N_("_Patterns")); + + gimp_plugin_menu_branch_register ("<Image>/File/Create", + N_("_Web Page Themes")); + gimp_plugin_menu_branch_register ("<Image>/File/Create/Web Page Themes", + N_("_Alien Glow")); + gimp_plugin_menu_branch_register ("<Image>/File/Create/Web Page Themes", + N_("_Beveled Pattern")); + gimp_plugin_menu_branch_register ("<Image>/File/Create/Web Page Themes", + N_("_Classic.Gimp.Org")); + + gimp_plugin_menu_branch_register ("<Image>/Filters", + N_("Alpha to _Logo")); + + gimp_install_temp_proc ("script-fu-refresh", + N_("Re-read all available Script-Fu scripts"), + "Re-read all available Script-Fu scripts", + "Spencer Kimball & Peter Mattis", + "Spencer Kimball & Peter Mattis", + "1997", + N_("_Refresh Scripts"), + NULL, + GIMP_TEMPORARY, + G_N_ELEMENTS (args), 0, + args, NULL, + script_fu_refresh_proc); + + gimp_plugin_menu_register ("script-fu-refresh", + "<Image>/Filters/Languages/Script-Fu"); +} + +static void +script_fu_refresh_proc (const gchar *name, + gint nparams, + const GimpParam *params, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[1]; + GimpPDBStatusType status; + + if (script_fu_interface_is_active ()) + { + g_message (_("You can not use \"Refresh Scripts\" while a " + "Script-Fu dialog box is open. Please close " + "all Script-Fu windows and try again.")); + + status = GIMP_PDB_EXECUTION_ERROR; + } + else + { + /* Reload all of the available scripts */ + GList *path = script_fu_search_path (); + + script_fu_find_scripts (path); + + g_list_free_full (path, (GDestroyNotify) g_object_unref); + + status = GIMP_PDB_SUCCESS; + } + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = status; +} diff --git a/plug-ins/script-fu/scripts/Makefile.am b/plug-ins/script-fu/scripts/Makefile.am new file mode 100644 index 0000000..4cce60d --- /dev/null +++ b/plug-ins/script-fu/scripts/Makefile.am @@ -0,0 +1,70 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = images + +scriptdatadir = $(gimpdatadir)/scripts + +scripts = \ + script-fu.init \ + script-fu-compat.init \ + plug-in-compat.init \ + add-bevel.scm \ + addborder.scm \ + blend-anim.scm \ + burn-in-anim.scm \ + carve-it.scm \ + chrome-it.scm \ + circuit.scm \ + clothify.scm \ + coffee.scm \ + copy-visible.scm \ + difference-clouds.scm \ + distress-selection.scm \ + drop-shadow.scm \ + erase-rows.scm \ + font-map.scm \ + fuzzyborder.scm \ + gimp-online.scm \ + gradient-example.scm \ + grid-system.scm \ + guides-from-selection.scm \ + guides-new.scm \ + guides-new-percent.scm \ + guides-remove-all.scm \ + lava.scm \ + line-nova.scm \ + mkbrush.scm \ + old-photo.scm \ + palette-export.scm \ + paste-as-brush.scm \ + paste-as-pattern.scm \ + perspective-shadow.scm \ + predator.scm \ + reverse-layers.scm \ + ripply-anim.scm \ + round-corners.scm \ + script-fu-set-cmap.scm \ + script-fu-util.scm \ + select-to-brush.scm \ + select-to-image.scm \ + select-to-pattern.scm \ + selection-round.scm \ + slide.scm \ + spinning-globe.scm \ + spyrogimp.scm \ + tileblur.scm \ + unsharp-mask.scm \ + waves-anim.scm \ + weave.scm \ + xach-effect.scm + +test_scripts = \ + contactsheet.scm \ + test-sphere.scm \ + ts-helloworld.scm + + +scriptdata_DATA = $(scripts) + + +EXTRA_DIST = $(scripts) $(test_scripts) diff --git a/plug-ins/script-fu/scripts/Makefile.in b/plug-ins/script-fu/scripts/Makefile.in new file mode 100644 index 0000000..e4554bf --- /dev/null +++ b/plug-ins/script-fu/scripts/Makefile.in @@ -0,0 +1,1044 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = plug-ins/script-fu/scripts +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(scriptdatadir)" +DATA = $(scriptdata_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = images +scriptdatadir = $(gimpdatadir)/scripts +scripts = \ + script-fu.init \ + script-fu-compat.init \ + plug-in-compat.init \ + add-bevel.scm \ + addborder.scm \ + blend-anim.scm \ + burn-in-anim.scm \ + carve-it.scm \ + chrome-it.scm \ + circuit.scm \ + clothify.scm \ + coffee.scm \ + copy-visible.scm \ + difference-clouds.scm \ + distress-selection.scm \ + drop-shadow.scm \ + erase-rows.scm \ + font-map.scm \ + fuzzyborder.scm \ + gimp-online.scm \ + gradient-example.scm \ + grid-system.scm \ + guides-from-selection.scm \ + guides-new.scm \ + guides-new-percent.scm \ + guides-remove-all.scm \ + lava.scm \ + line-nova.scm \ + mkbrush.scm \ + old-photo.scm \ + palette-export.scm \ + paste-as-brush.scm \ + paste-as-pattern.scm \ + perspective-shadow.scm \ + predator.scm \ + reverse-layers.scm \ + ripply-anim.scm \ + round-corners.scm \ + script-fu-set-cmap.scm \ + script-fu-util.scm \ + select-to-brush.scm \ + select-to-image.scm \ + select-to-pattern.scm \ + selection-round.scm \ + slide.scm \ + spinning-globe.scm \ + spyrogimp.scm \ + tileblur.scm \ + unsharp-mask.scm \ + waves-anim.scm \ + weave.scm \ + xach-effect.scm + +test_scripts = \ + contactsheet.scm \ + test-sphere.scm \ + ts-helloworld.scm + +scriptdata_DATA = $(scripts) +EXTRA_DIST = $(scripts) $(test_scripts) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plug-ins/script-fu/scripts/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plug-ins/script-fu/scripts/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-scriptdataDATA: $(scriptdata_DATA) + @$(NORMAL_INSTALL) + @list='$(scriptdata_DATA)'; test -n "$(scriptdatadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(scriptdatadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(scriptdatadir)" || exit 1; \ + fi; \ + 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)$(scriptdatadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(scriptdatadir)" || exit $$?; \ + done + +uninstall-scriptdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(scriptdata_DATA)'; test -n "$(scriptdatadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(scriptdatadir)'; $(am__uninstall_files_from_dir) + +# 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, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(scriptdatadir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-scriptdataDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-scriptdataDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir 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-scriptdataDATA install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-scriptdataDATA + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/plug-ins/script-fu/scripts/add-bevel.scm b/plug-ins/script-fu/scripts/add-bevel.scm new file mode 100644 index 0000000..6e0f951 --- /dev/null +++ b/plug-ins/script-fu/scripts/add-bevel.scm @@ -0,0 +1,202 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; add-bevel.scm version 1.04 +; Time-stamp: <2004-02-09 17:07:06 simon> +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; Copyright (C) 1997 Andrew Donkin (ard@cs.waikato.ac.nz) +; Contains code from add-shadow.scm by Sven Neumann +; (neumanns@uni-duesseldorf.de) (thanks Sven). +; +; Adds a bevel to an image. See http://www.cs.waikato.ac.nz/~ard/gimp/ +; +; If there is a selection, it is bevelled. +; Otherwise if there is an alpha channel, the selection is taken from it +; and bevelled. +; Otherwise the part of the layer inside the image boundaries is bevelled. +; +; The selection is set on exit, so Select->Invert then Edit->Clear will +; leave a cut-out. Then use Sven's add-shadow for that +; floating-bumpmapped-texture cliche. + +; +; 1.01: now works on offset layers. +; 1.02: has crop-pixel-border option to trim one pixel off each edge of the +; bevelled image. Bumpmapping leaves edge pixels unchanged, which +; looks bad. Oddly, this is not apparent in GIMP - you have to +; save the image and load it into another viewer. First noticed in +; Nutscrape. +; Changed path (removed "filters/"). +; 1.03: adds one-pixel border before bumpmapping, and removes it after. +; Got rid of the crop-pixel-border option (no longer reqd). +; 1.04: Fixed undo handling, ensure that bumpmap is big enough, +; (instead of resizing the image). Removed references to outdated +; bumpmap plugin. (Simon) +; 1.05 When there is no selection, bevel the whole layer instead of the +; whole image (which was broken in the first place). +; Also fixed some bugs with setting the selection when there is no +; initial selection. (Barak Itkin) +; + +(define (script-fu-add-bevel img + drawable + thickness + work-on-copy + keep-bump-layer) + + (let* ( + (index 1) + (greyness 0) + (thickness (abs thickness)) + (type (car (gimp-drawable-type-with-alpha drawable))) + (image (if (= work-on-copy TRUE) (car (gimp-image-duplicate img)) img)) + (pic-layer (car (gimp-image-get-active-drawable image))) + (offsets (gimp-drawable-offsets pic-layer)) + (width (car (gimp-drawable-width pic-layer))) + (height (car (gimp-drawable-height pic-layer))) + + ; Bumpmap has a one pixel border on each side + (bump-layer (car (gimp-layer-new image + (+ width 2) + (+ height 2) + RGB-IMAGE + _"Bumpmap" + 100 + LAYER-MODE-NORMAL))) + + (selection-exists (car (gimp-selection-bounds image))) + (selection 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + ; disable undo on copy, start group otherwise + (if (= work-on-copy TRUE) + (gimp-image-undo-disable image) + (gimp-image-undo-group-start image) + ) + + (gimp-image-insert-layer image bump-layer 0 1) + + ; If the layer we're bevelling is offset from the image's origin, we + ; have to do the same to the bumpmap + (gimp-layer-set-offsets bump-layer (- (car offsets) 1) + (- (cadr offsets) 1)) + + ;------------------------------------------------------------ + ; + ; Set the selection to the area we want to bevel. + ; + (if (= selection-exists 0) + (gimp-image-select-item image CHANNEL-OP-REPLACE pic-layer) + ) + + ; Store it for later. + (set! selection (car (gimp-selection-save image))) + ; Try to lose the jaggies + (gimp-selection-feather image 2) + + ;------------------------------------------------------------ + ; + ; Initialise our bumpmap + ; + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-fill bump-layer FILL-BACKGROUND) + + (while (and (< index thickness) + (= (car (gimp-selection-is-empty image)) FALSE) + ) + (set! greyness (/ (* index 255) thickness)) + (gimp-context-set-background (list greyness greyness greyness)) + ;(gimp-selection-feather image 1) ;Stop the slopey jaggies? + (gimp-drawable-edit-fill bump-layer FILL-BACKGROUND) + (gimp-selection-shrink image 1) + (set! index (+ index 1)) + ) + ; Now the white interior + (if (= (car (gimp-selection-is-empty image)) FALSE) + (begin + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill bump-layer FILL-BACKGROUND) + ) + ) + + ;------------------------------------------------------------ + ; + ; Do the bump. + ; + (gimp-selection-none image) + + ; To further lessen jaggies? + ;(plug-in-gauss-rle RUN-NONINTERACTIVE image bump-layer thickness TRUE TRUE) + + + ; + ; BUMPMAP INVOCATION: + ; + (plug-in-bump-map RUN-NONINTERACTIVE image pic-layer bump-layer 125 45 3 0 0 0 0 TRUE FALSE 1) + + ;------------------------------------------------------------ + ; + ; Restore things + ; + (if (= selection-exists 0) + (gimp-selection-none image) ; No selection to start with + (gimp-image-select-item image CHANNEL-OP-REPLACE selection) + ) + ; If they started with a selection, they can Select->Invert then + ; Edit->Clear for a cutout. + + ; clean up + (gimp-image-remove-channel image selection) + (if (= keep-bump-layer TRUE) + (gimp-item-set-visible bump-layer 0) + (gimp-image-remove-layer image bump-layer) + ) + + (gimp-image-set-active-layer image pic-layer) + + ; enable undo / end undo group + (if (= work-on-copy TRUE) + (begin + (gimp-display-new image) + (gimp-image-undo-enable image) + ) + (gimp-image-undo-group-end image) + ) + + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-add-bevel" + _"Add B_evel..." + _"Add a beveled border to an image" + "Andrew Donkin <ard@cs.waikato.ac.nz>" + "Andrew Donkin" + "1997/11/06" + "RGB*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Thickness" '(5 0 30 1 2 0 0) + SF-TOGGLE _"Work on copy" TRUE + SF-TOGGLE _"Keep bump layer" FALSE +) + +(script-fu-menu-register "script-fu-add-bevel" "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/addborder.scm b/plug-ins/script-fu/scripts/addborder.scm new file mode 100644 index 0000000..ed47feb --- /dev/null +++ b/plug-ins/script-fu/scripts/addborder.scm @@ -0,0 +1,177 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; Copyright (C) 1997 Andy Thomas alt@picnic.demon.co.uk +; +; Version 0.2 10.6.97 Changed to new script-fu interface in 0.99.10 + +; Delta the color by the given amount. Check for boundary conditions +; If < 0 set to zero +; If > 255 set to 255 +; Return the new value + +(define (script-fu-addborder aimg adraw xsize ysize color dvalue) + + (define (deltacolor col delta) + (let* ((newcol (+ col delta))) + (if (< newcol 0) (set! newcol 0)) + (if (> newcol 255) (set! newcol 255)) + newcol + ) + ) + + (define (adjcolor col delta) + (mapcar (lambda (x) (deltacolor x delta)) col) + ) + + (define (gen_top_array xsize ysize owidth oheight width height) + (let* ((n_array (cons-array 10 'double))) + (aset n_array 0 0 ) + (aset n_array 1 0 ) + (aset n_array 2 xsize) + (aset n_array 3 ysize) + (aset n_array 4 (+ xsize owidth)) + (aset n_array 5 ysize) + (aset n_array 6 width) + (aset n_array 7 0 ) + (aset n_array 8 0 ) + (aset n_array 9 0 ) + n_array) + ) + + (define (gen_left_array xsize ysize owidth oheight width height) + (let* ((n_array (cons-array 10 'double))) + (aset n_array 0 0 ) + (aset n_array 1 0 ) + (aset n_array 2 xsize) + (aset n_array 3 ysize) + (aset n_array 4 xsize) + (aset n_array 5 (+ ysize oheight)) + (aset n_array 6 0 ) + (aset n_array 7 height ) + (aset n_array 8 0 ) + (aset n_array 9 0 ) + n_array) + ) + + (define (gen_right_array xsize ysize owidth oheight width height) + (let* ((n_array (cons-array 10 'double))) + (aset n_array 0 width ) + (aset n_array 1 0 ) + (aset n_array 2 (+ xsize owidth)) + (aset n_array 3 ysize) + (aset n_array 4 (+ xsize owidth)) + (aset n_array 5 (+ ysize oheight)) + (aset n_array 6 width) + (aset n_array 7 height) + (aset n_array 8 width ) + (aset n_array 9 0 ) + n_array) + ) + + (define (gen_bottom_array xsize ysize owidth oheight width height) + (let* ((n_array (cons-array 10 'double))) + (aset n_array 0 0 ) + (aset n_array 1 height) + (aset n_array 2 xsize) + (aset n_array 3 (+ ysize oheight)) + (aset n_array 4 (+ xsize owidth)) + (aset n_array 5 (+ ysize oheight)) + (aset n_array 6 width) + (aset n_array 7 height) + (aset n_array 8 0 ) + (aset n_array 9 height) + n_array) + ) + + (let* ((img (car (gimp-item-get-image adraw))) + (owidth (car (gimp-image-width img))) + (oheight (car (gimp-image-height img))) + (width (+ owidth (* 2 xsize))) + (height (+ oheight (* 2 ysize))) + (layer (car (gimp-layer-new img + width height + (car (gimp-drawable-type-with-alpha adraw)) + _"Border Layer" 100 LAYER-MODE-NORMAL)))) + + (gimp-context-push) + (gimp-context-set-paint-mode LAYER-MODE-NORMAL) + (gimp-context-set-opacity 100.0) + (gimp-context-set-antialias FALSE) + (gimp-context-set-feather FALSE) + + (gimp-image-undo-group-start img) + + (gimp-image-resize img + width + height + xsize + ysize) + + (gimp-image-insert-layer img layer 0 0) + (gimp-drawable-fill layer FILL-TRANSPARENT) + + (gimp-context-set-background (adjcolor color dvalue)) + (gimp-image-select-polygon img + CHANNEL-OP-REPLACE + 10 + (gen_top_array xsize ysize owidth oheight width height)) + (gimp-drawable-edit-fill layer FILL-BACKGROUND) + (gimp-context-set-background (adjcolor color (/ dvalue 2))) + (gimp-image-select-polygon img + CHANNEL-OP-REPLACE + 10 + (gen_left_array xsize ysize owidth oheight width height)) + (gimp-drawable-edit-fill layer FILL-BACKGROUND) + (gimp-context-set-background (adjcolor color (- 0 (/ dvalue 2)))) + (gimp-image-select-polygon img + CHANNEL-OP-REPLACE + 10 + (gen_right_array xsize ysize owidth oheight width height)) + + (gimp-drawable-edit-fill layer FILL-BACKGROUND) + (gimp-context-set-background (adjcolor color (- 0 dvalue))) + (gimp-image-select-polygon img + CHANNEL-OP-REPLACE + 10 + (gen_bottom_array xsize ysize owidth oheight width height)) + + (gimp-drawable-edit-fill layer FILL-BACKGROUND) + (gimp-selection-none img) + (gimp-image-undo-group-end img) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-addborder" + _"Add _Border..." + _"Add a border around an image" + "Andy Thomas <alt@picnic.demon.co.uk>" + "Andy Thomas" + "6/10/97" + "*" + SF-IMAGE "Input image" 0 + SF-DRAWABLE "Input drawable" 0 + SF-ADJUSTMENT _"Border X size" '(12 1 250 1 10 0 1) + SF-ADJUSTMENT _"Border Y size" '(12 1 250 1 10 0 1) + SF-COLOR _"Border color" '(38 31 207) + SF-ADJUSTMENT _"Delta value on color" '(25 1 255 1 10 0 1) +) + +(script-fu-menu-register "script-fu-addborder" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/blend-anim.scm b/plug-ins/script-fu/scripts/blend-anim.scm new file mode 100644 index 0000000..517b1c5 --- /dev/null +++ b/plug-ins/script-fu/scripts/blend-anim.scm @@ -0,0 +1,242 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; blend-anim.scm version 1.03 1999/12/21 +; +; CHANGE-LOG: +; 1.00 - initial release +; 1.01 - some code cleanup, no real changes +; 1.02 - use gimp-message to output an error message if called +; with less than three layers +; 1.03 - only call blur plugin when blut-radius >= 1.0 +; +; Copyright (C) 1997-1999 Sven Neumann <sven@gimp.org> +; +; +; Blends two or more layers over a background, so that an animation can +; be saved. A minimum of three layers is required. + +(define (script-fu-blend-anim img + drawable + frames + max-blur + looped) + + (define (multi-raise-layer image layer times) + (while (> times 0) + (gimp-image-raise-item image layer) + (set! times (- times 1)) + ) + ) + + (let* ( + (max-blur (max max-blur 0)) + (frames (max frames 0)) + (image (car (gimp-image-duplicate img))) + (width (car (gimp-image-width image))) + (height (car (gimp-image-height image))) + (layers (gimp-image-get-layers image)) + (num-layers (car layers)) + (layer-array (cadr layers)) + (slots (- num-layers 2)) + (bg-layer (aref layer-array (- num-layers 1))) + (max-width 0) + (max-height 0) + (offset-x 0) + (offset-y 0) + ) + + (if (> num-layers 2) + (begin + (gimp-image-undo-disable image) + + (if (= looped TRUE) + ; add a copy of the lowest blend layer on top + (let* ((copy (car (gimp-layer-copy + (aref layer-array (- num-layers 2)) TRUE)))) + (gimp-image-insert-layer image copy 0 0) + (set! layers (gimp-image-get-layers image)) + (set! num-layers (car layers)) + (set! layer-array (cadr layers)) + (set! slots (- num-layers 2)) + (set! bg-layer (aref layer-array (- num-layers 1))))) + + ; make all layers invisible and check for sizes + (let* ((min-offset-x width) + (min-offset-y height) + (layer-count slots)) + (gimp-item-set-visible bg-layer FALSE) + (while (> layer-count -1) + (let* ((layer (aref layer-array layer-count)) + (layer-width (+ (car (gimp-drawable-width layer)) + (* max-blur 2))) + (layer-height (+ (car (gimp-drawable-height layer)) + (* max-blur 2))) + (layer-offsets (gimp-drawable-offsets layer)) + (layer-offset-x (- (car layer-offsets) max-blur)) + (layer-offset-y (- (cadr layer-offsets) max-blur))) + (gimp-item-set-visible layer FALSE) + (set! max-width (max max-width layer-width)) + (set! max-height (max max-height layer-height)) + (set! min-offset-x (min min-offset-x layer-offset-x)) + (set! min-offset-y (min min-offset-y layer-offset-y)) + (set! layer-count (- layer-count 1)))) + (set! offset-x (- (car (gimp-drawable-offsets bg-layer)) + min-offset-x)) + (set! offset-y (- (cadr (gimp-drawable-offsets bg-layer)) + min-offset-y))) + + ; create intermediate frames by merging copies of adjacent layers + ; with the background layer + (let* ((layer-count slots)) + (while (> layer-count 0) + (let* ((frame-count frames) + (lower-layer (aref layer-array layer-count)) + (upper-layer (aref layer-array (- layer-count 1)))) + (while (> frame-count 0) + (let* ((opacity (* (/ frame-count (+ frames 1)) 100)) + (blur (/ (* opacity max-blur) 100)) + (upper-copy (car (gimp-layer-copy upper-layer TRUE))) + (lower-copy (car (gimp-layer-copy lower-layer TRUE))) + (bg-copy (car (gimp-layer-copy bg-layer TRUE)))) + (gimp-image-insert-layer image bg-copy 0 0) + (gimp-image-insert-layer image lower-copy 0 0) + (gimp-image-insert-layer image upper-copy 0 0) + (gimp-item-set-visible upper-copy TRUE) + (gimp-item-set-visible lower-copy TRUE) + (gimp-item-set-visible bg-copy TRUE) + (gimp-layer-set-opacity upper-copy (- 100 opacity)) + (gimp-layer-set-opacity lower-copy opacity) + (gimp-layer-set-opacity bg-copy 100) + (if (> max-blur 0) + (let* ((layer-width (car (gimp-drawable-width upper-copy))) + (layer-height (car (gimp-drawable-height upper-copy)))) + (gimp-layer-set-lock-alpha upper-copy FALSE) + (gimp-layer-resize upper-copy + (+ layer-width (* blur 2)) + (+ layer-height (* blur 2)) + blur + blur) + (if (>= blur 1.0) + (plug-in-gauss-rle RUN-NONINTERACTIVE + image + upper-copy + blur + TRUE TRUE)) + (set! blur (- max-blur blur)) + (gimp-layer-set-lock-alpha lower-copy FALSE) + (set! layer-width (car (gimp-drawable-width + lower-copy))) + (set! layer-height (car (gimp-drawable-height + lower-copy))) + (gimp-layer-resize lower-copy + (+ layer-width (* blur 2)) + (+ layer-height (* blur 2)) + blur + blur) + (if (>= blur 1.0) + (plug-in-gauss-rle RUN-NONINTERACTIVE + image + lower-copy + blur + TRUE TRUE)))) + (gimp-layer-resize bg-copy + max-width + max-height + offset-x + offset-y) + (let* ((merged-layer (car (gimp-image-merge-visible-layers + image CLIP-TO-IMAGE)))) + (gimp-item-set-visible merged-layer FALSE)) + (set! frame-count (- frame-count 1)))) + (set! layer-count (- layer-count 1))))) + + ; merge all original blend layers but the lowest one + ; with copies of the background layer + (let* ((layer-count 0)) + (while (< layer-count slots) + (let* ((orig-layer (aref layer-array layer-count)) + (bg-copy (car (gimp-layer-copy bg-layer TRUE)))) + (gimp-image-insert-layer image + bg-copy + -1 + (* layer-count (+ frames 1))) + (multi-raise-layer image + orig-layer + (+ (* (- slots layer-count) frames) 1)) + (gimp-item-set-visible orig-layer TRUE) + (gimp-item-set-visible bg-copy TRUE) + (gimp-layer-resize bg-copy + max-width + max-height + offset-x + offset-y) + (let* ((merged-layer (car (gimp-image-merge-visible-layers + image CLIP-TO-IMAGE)))) + (gimp-item-set-visible merged-layer FALSE)) + (set! layer-count (+ layer-count 1))))) + + ; merge the lowest blend layer with the background layer + (let* ((orig-layer (aref layer-array (- num-layers 2)))) + (gimp-item-set-visible bg-layer TRUE) + (gimp-item-set-visible orig-layer TRUE) + (gimp-image-merge-visible-layers image CLIP-TO-IMAGE)) + + ; make all layers visible again + (let* ((result-layers (gimp-image-get-layers image)) + (num-result-layers (car result-layers)) + (result-layer-array (cadr result-layers)) + (layer-count (- num-result-layers 1))) + (while (> layer-count -1) + (let* ((layer (aref result-layer-array layer-count)) + (name (string-append _"Frame" " " + (number->string + (- num-result-layers layer-count) 10)))) + (gimp-item-set-visible layer TRUE) + (gimp-item-set-name layer name) + (set! layer-count (- layer-count 1)))) + + (if (= looped TRUE) + ; remove the topmost layer + (gimp-image-remove-layer image (aref result-layer-array 0)))) + + (gimp-image-undo-enable image) + (gimp-display-new image) + (gimp-displays-flush) + ) + + (gimp-message _"Blend Animation needs at least three source layers") + ) + ) +) + +(script-fu-register "script-fu-blend-anim" + _"_Blend..." + _"Create intermediate layers to blend two or more layers over a background as an animation" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "1999/12/21" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Intermediate frames" '(3 1 1024 1 10 0 1) + SF-ADJUSTMENT _"Max. blur radius" '(0 0 1024 1 10 0 1) + SF-TOGGLE _"Looped" TRUE +) + +(script-fu-menu-register "script-fu-blend-anim" + "<Image>/Filters/Animation/Animators") diff --git a/plug-ins/script-fu/scripts/burn-in-anim.scm b/plug-ins/script-fu/scripts/burn-in-anim.scm new file mode 100644 index 0000000..4842e8a --- /dev/null +++ b/plug-ins/script-fu/scripts/burn-in-anim.scm @@ -0,0 +1,243 @@ +; +; burn-in-anim.scm V2.1 - script-fu for GIMP 1.1 and higher +; +; Copyright (C) 9/2000 Roland Berger +; roland@fuchur.leute.server.de +; http://fuchur.leute.server.de +; +; Let text appear and fade out with a "burn-in" like SFX. +; Works on an image with a text and a background layer +; +; Copying Policy: GNU Public License http://www.gnu.org +; + +(define (script-fu-burn-in-anim org-img + org-layer + glow-color + fadeout + bl-width + corona-width + after-glow + show-glow + optimize + speed) + + (let* ( + ;--- main variable: "bl-x" runs from 0 to layer-width + (bl-x 0) + (frame-nr 0) + (img 0) + (source-layer 0) + (bg-source-layer 0) + (source-layer-width 0) + (bg-layer 0) + (bg-layer-name 0) + (bl-layer 0) + (bl-layer-name 0) + (bl-mask 0) + (bl-layer-width 0) + (bl-height 0) + (bl-x-off 0) + (bl-y-off 0) + (nofadeout-bl-x-off 0) + (nofadeout-bl-width 0) + (blended-layer 0) + (img-display 0) + ) + + (if (< speed 1) + (set! speed (* -1 speed)) ) + + ;--- check image and work on a copy + (if (and (= (car (gimp-image-get-layers org-img)) 2) + (= (car (gimp-image-get-floating-sel org-img)) -1)) + + ;--- main program structure starts here, begin of "if-1" + (begin + (gimp-context-push) + (gimp-context-set-defaults) + + (set! img (car (gimp-image-duplicate org-img))) + (gimp-image-undo-disable img) + (if (> (car (gimp-drawable-type org-layer)) 1 ) + (gimp-image-convert-rgb img)) + (set! source-layer (aref (cadr (gimp-image-get-layers img)) 0 )) + (set! bg-source-layer (aref (cadr (gimp-image-get-layers img)) 1 )) + (set! source-layer-width (car (gimp-drawable-width source-layer))) + + ;--- hide layers, cause we want to "merge visible layers" later + (gimp-item-set-visible source-layer FALSE) + (gimp-item-set-visible bg-source-layer FALSE) + + ;--- process image horizontal with pixel-speed + (while (< bl-x (+ source-layer-width bl-width)) + (set! bl-layer (car (gimp-layer-copy source-layer TRUE))) + (set! bl-layer-name (string-append "fr-nr" + (number->string frame-nr 10) ) ) + + (gimp-image-insert-layer img bl-layer 0 -2) + (gimp-item-set-name bl-layer bl-layer-name) + (gimp-item-set-visible bl-layer TRUE) + (gimp-layer-set-lock-alpha bl-layer TRUE) + (gimp-layer-add-alpha bl-layer) + + ;--- add an alpha mask for blending and select it + (gimp-image-select-item img CHANNEL-OP-REPLACE bl-layer) + (set! bl-mask (car (gimp-layer-create-mask bl-layer ADD-MASK-BLACK))) + (gimp-layer-add-mask bl-layer bl-mask) + + ;--- handle layer geometry + (set! bl-layer-width source-layer-width) + (set! bl-height (car (gimp-drawable-height bl-layer))) + (set! bl-x-off (- bl-x bl-width)) + (set! bl-x-off (+ bl-x-off (car (gimp-drawable-offsets bl-layer)))) + (set! bl-y-off (cadr (gimp-drawable-offsets bl-layer))) + + ;--- select a rectangular area to blend + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE bl-x-off bl-y-off bl-width bl-height) + ;--- select at least 1 pixel! + (gimp-image-select-rectangle img CHANNEL-OP-ADD bl-x-off bl-y-off (+ bl-width 1) bl-height) + + (if (= fadeout FALSE) + (begin + (set! nofadeout-bl-x-off (car (gimp-drawable-offsets bl-layer))) + (set! nofadeout-bl-width (+ nofadeout-bl-x-off bl-x)) + (set! nofadeout-bl-width (max nofadeout-bl-width 1)) + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE + nofadeout-bl-x-off bl-y-off + nofadeout-bl-width bl-height) + ) + ) + + ;--- alpha blending text to trans (fadeout) + (gimp-context-set-foreground '(255 255 255)) + (gimp-context-set-background '( 0 0 0)) + (if (= fadeout TRUE) + (begin + ; blend with 20% offset to get less transparency in the front + (gimp-context-set-gradient-fg-bg-rgb) + (gimp-drawable-edit-gradient-fill bl-mask + GRADIENT-LINEAR 20 + FALSE 0 0 + TRUE + (+ bl-x-off bl-width) 0 + bl-x-off 0) + ) + ) + + (if (= fadeout FALSE) + (begin + (gimp-context-set-foreground '(255 255 255)) + (gimp-drawable-edit-fill bl-mask FILL-FOREGROUND) + ) + ) + + (gimp-layer-remove-mask bl-layer MASK-APPLY) + + ;--- add bright glow in front + (if (= show-glow TRUE) + (begin + ;--- add some brightness to whole text + (if (= fadeout TRUE) + (gimp-drawable-brightness-contrast bl-layer 0.787 0) + ) + + ;--- blend glow color inside the letters + (gimp-context-set-foreground glow-color) + (gimp-context-set-gradient-fg-transparent) + (gimp-drawable-edit-gradient-fill bl-layer + GRADIENT-LINEAR 0 + FALSE 0 0 + TRUE + (+ bl-x-off bl-width) 0 + (- (+ bl-x-off bl-width) after-glow) 0) + + ;--- add corona effect + (gimp-image-select-item img CHANNEL-OP-REPLACE bl-layer) + (gimp-selection-sharpen img) + (gimp-selection-grow img corona-width) + (gimp-layer-set-lock-alpha bl-layer FALSE) + (gimp-selection-feather img corona-width) + (gimp-context-set-foreground glow-color) + (gimp-drawable-edit-gradient-fill bl-layer + GRADIENT-LINEAR 0 + FALSE 0 0 + TRUE + (- (+ bl-x-off bl-width) corona-width) 0 + (- (+ bl-x-off bl-width) after-glow) 0) + ) + ) + + ;--- merge with bg layer + (set! bg-layer (car (gimp-layer-copy bg-source-layer FALSE))) + (gimp-image-insert-layer img bg-layer 0 -1) + (gimp-image-lower-item img bg-layer) + (set! bg-layer-name (string-append "bg-" + (number->string frame-nr 10))) + (gimp-item-set-name bg-layer bg-layer-name) + (gimp-item-set-visible bg-layer TRUE) + (set! blended-layer (car (gimp-image-merge-visible-layers img + CLIP-TO-IMAGE))) + ;(set! blended-layer bl-layer) + (gimp-item-set-visible blended-layer FALSE) + + ;--- end of "while" loop + (set! frame-nr (+ frame-nr 1)) + (set! bl-x (+ bl-x speed)) + ) + + ;--- finalize the job + (gimp-selection-none img) + (gimp-image-remove-layer img source-layer) + (gimp-image-remove-layer img bg-source-layer) + + (gimp-image-set-filename img "burn-in") + + (if (= optimize TRUE) + (begin + (gimp-image-convert-indexed img CONVERT-DITHER-FS CONVERT-PALETTE-WEB 250 FALSE TRUE "") + (set! img (car (plug-in-animationoptimize RUN-NONINTERACTIVE + img + blended-layer))) + ) + ) + + (gimp-item-set-visible (aref (cadr (gimp-image-get-layers img)) 0) + TRUE) + (gimp-image-undo-enable img) + (gimp-image-clean-all img) + (set! img-display (car (gimp-display-new img))) + + (gimp-displays-flush) + + (gimp-context-pop) + ) + + ;--- false form of "if-1" + (gimp-message _"The Burn-In script needs two layers in total. A foreground layer with transparency and a background layer.") + ) + ) +) + + +(script-fu-register "script-fu-burn-in-anim" + _"B_urn-In..." + _"Create intermediate layers to produce an animated 'burn-in' transition between two layers" + "Roland Berger roland@fuchur.leute.server.de" + "Roland Berger" + "January 2001" + "RGBA GRAYA INDEXEDA" + SF-IMAGE "The image" 0 + SF-DRAWABLE "Layer to animate" 0 + SF-COLOR _"Glow color" "white" + SF-TOGGLE _"Fadeout" FALSE + SF-VALUE _"Fadeout width" "100" + SF-VALUE _"Corona width" "7" + SF-VALUE _"After glow" "50" + SF-TOGGLE _"Add glowing" TRUE + SF-TOGGLE _"Prepare for GIF" FALSE + SF-VALUE _"Speed (pixels/frame)" "50" +) + +(script-fu-menu-register "script-fu-burn-in-anim" + "<Image>/Filters/Animation/Animators") diff --git a/plug-ins/script-fu/scripts/carve-it.scm b/plug-ins/script-fu/scripts/carve-it.scm new file mode 100644 index 0000000..a88fa08 --- /dev/null +++ b/plug-ins/script-fu/scripts/carve-it.scm @@ -0,0 +1,205 @@ +; CARVE-IT +; Carving, embossing, & stamping +; Process taken from "The Photoshop 3 WOW! Book" +; http://www.peachpit.com +; This script requires a grayscale image containing a single layer. +; This layer is used as the mask for the carving effect +; NOTE: This script requires the image to be carved to either be an +; RGB color or grayscale image with a single layer. An indexed file +; can not be used due to the use of gimp-drawable-histogram and +; gimp-drawable-levels. + + +(define (carve-scale val scale) + (* (sqrt val) scale)) + +(define (calculate-inset-gamma img layer) + (let* ((stats (gimp-drawable-histogram layer 0 0.0 1.0)) + (mean (car stats))) + (cond ((< mean 127) (+ 1.0 (* 0.5 (/ (- 127 mean) 127.0)))) + ((>= mean 127) (- 1.0 (* 0.5 (/ (- mean 127) 127.0))))))) + + +(define (copy-layer-carve-it dest-image dest-drawable source-image source-drawable) + (gimp-selection-all dest-image) + (gimp-drawable-edit-clear dest-drawable) + (gimp-selection-none dest-image) + (gimp-selection-all source-image) + (gimp-edit-copy source-drawable) + (let ((floating-sel (car (gimp-edit-paste dest-drawable FALSE)))) + (gimp-floating-sel-anchor floating-sel))) + + + +(define (script-fu-carve-it mask-img mask-drawable bg-layer carve-white) + (let* ( + (width (car (gimp-drawable-width mask-drawable))) + (height (car (gimp-drawable-height mask-drawable))) + (type (car (gimp-drawable-type bg-layer))) + (img (car (gimp-image-new width height (cond ((= type RGB-IMAGE) RGB) + ((= type RGBA-IMAGE) RGB) + ((= type GRAY-IMAGE) GRAY) + ((= type GRAYA-IMAGE) GRAY) + ((= type INDEXED-IMAGE) INDEXED) + ((= type INDEXEDA-IMAGE) INDEXED))))) + (size (min width height)) + (offx (carve-scale size 0.33)) + (offy (carve-scale size 0.25)) + (feather (carve-scale size 0.3)) + (brush-size (carve-scale size 0.3)) + (brush-name (car (gimp-brush-new "Carve It"))) + (mask-fs 0) + (mask (car (gimp-channel-new img width height "Engraving Mask" 50 '(0 0 0)))) + (inset-gamma (calculate-inset-gamma (car (gimp-item-get-image bg-layer)) bg-layer)) + (mask-fat 0) + (mask-emboss 0) + (mask-highlight 0) + (mask-shadow 0) + (shadow-layer 0) + (highlight-layer 0) + (cast-shadow-layer 0) + (csl-mask 0) + (inset-layer 0) + (il-mask 0) + (bg-width (car (gimp-drawable-width bg-layer))) + (bg-height (car (gimp-drawable-height bg-layer))) + (bg-type (car (gimp-drawable-type bg-layer))) + (bg-image (car (gimp-item-get-image bg-layer))) + (layer1 (car (gimp-layer-new img bg-width bg-height bg-type "Layer1" 100 LAYER-MODE-NORMAL))) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable img) + + (gimp-image-insert-layer img layer1 0 0) + + (gimp-selection-all img) + (gimp-drawable-edit-clear layer1) + (gimp-selection-none img) + (copy-layer-carve-it img layer1 bg-image bg-layer) + + (gimp-edit-copy mask-drawable) + (gimp-image-insert-channel img mask -1 0) + + (plug-in-tile RUN-NONINTERACTIVE img layer1 width height FALSE) + (set! mask-fs (car (gimp-edit-paste mask FALSE))) + (gimp-floating-sel-anchor mask-fs) + (if (= carve-white FALSE) + (gimp-drawable-invert mask FALSE)) + + (set! mask-fat (car (gimp-channel-copy mask))) + (gimp-image-insert-channel img mask-fat -1 0) + (gimp-image-select-item img CHANNEL-OP-REPLACE mask-fat) + + (gimp-brush-set-shape brush-name BRUSH-GENERATED-CIRCLE) + (gimp-brush-set-spikes brush-name 2) + (gimp-brush-set-hardness brush-name 1.0) + (gimp-brush-set-spacing brush-name 25) + (gimp-brush-set-aspect-ratio brush-name 1) + (gimp-brush-set-angle brush-name 0) + (cond (<= brush-size 17) (gimp-brush-set-radius brush-name (\ brush-size 2)) + (else gimp-brush-set-radius brush-name (\ 19 2))) + (gimp-context-set-brush brush-name) + + (gimp-context-set-foreground '(255 255 255)) + (gimp-drawable-edit-stroke-selection mask-fat) + (gimp-selection-none img) + + (set! mask-emboss (car (gimp-channel-copy mask-fat))) + (gimp-image-insert-channel img mask-emboss -1 0) + (plug-in-gauss-rle RUN-NONINTERACTIVE img mask-emboss feather TRUE TRUE) + (plug-in-emboss RUN-NONINTERACTIVE img mask-emboss 315.0 45.0 7 TRUE) + + (gimp-context-set-background '(180 180 180)) + (gimp-image-select-item img CHANNEL-OP-REPLACE mask-fat) + (gimp-selection-invert img) + (gimp-drawable-edit-fill mask-emboss FILL-BACKGROUND) + (gimp-image-select-item img CHANNEL-OP-REPLACE mask) + (gimp-drawable-edit-fill mask-emboss FILL-BACKGROUND) + (gimp-selection-none img) + + (set! mask-highlight (car (gimp-channel-copy mask-emboss))) + (gimp-image-insert-channel img mask-highlight -1 0) + (gimp-drawable-levels mask-highlight 0 + 0.7056 1.0 TRUE + 1.0 + 0.0 1.0 TRUE) + + (set! mask-shadow mask-emboss) + (gimp-drawable-levels mask-shadow 0 + 0.0 0.70586 TRUE + 1.0 + 0.0 1.0 TRUE) + + (gimp-edit-copy mask-shadow) + (set! shadow-layer (car (gimp-edit-paste layer1 FALSE))) + (gimp-floating-sel-to-layer shadow-layer) + (gimp-layer-set-mode shadow-layer LAYER-MODE-MULTIPLY) + + (gimp-edit-copy mask-highlight) + (set! highlight-layer (car (gimp-edit-paste shadow-layer FALSE))) + (gimp-floating-sel-to-layer highlight-layer) + (gimp-layer-set-mode highlight-layer LAYER-MODE-SCREEN) + + (gimp-edit-copy mask) + (set! cast-shadow-layer (car (gimp-edit-paste highlight-layer FALSE))) + (gimp-floating-sel-to-layer cast-shadow-layer) + (gimp-layer-set-mode cast-shadow-layer LAYER-MODE-MULTIPLY) + (gimp-layer-set-opacity cast-shadow-layer 75) + (plug-in-gauss-rle RUN-NONINTERACTIVE img cast-shadow-layer feather TRUE TRUE) + (gimp-item-transform-translate cast-shadow-layer offx offy) + + (set! csl-mask (car (gimp-layer-create-mask cast-shadow-layer ADD-MASK-BLACK))) + (gimp-layer-add-mask cast-shadow-layer csl-mask) + (gimp-image-select-item img CHANNEL-OP-REPLACE mask) + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill csl-mask FILL-BACKGROUND) + + (set! inset-layer (car (gimp-layer-copy layer1 TRUE))) + (gimp-image-insert-layer img inset-layer 0 1) + + (set! il-mask (car (gimp-layer-create-mask inset-layer ADD-MASK-BLACK))) + (gimp-layer-add-mask inset-layer il-mask) + (gimp-image-select-item img CHANNEL-OP-REPLACE mask) + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill il-mask FILL-BACKGROUND) + (gimp-selection-none img) + (gimp-selection-none bg-image) + (gimp-drawable-levels inset-layer 0 0.0 1.0 TRUE inset-gamma 0.0 1.0 TRUE) + (gimp-image-remove-channel img mask) + (gimp-image-remove-channel img mask-fat) + (gimp-image-remove-channel img mask-highlight) + (gimp-image-remove-channel img mask-shadow) + + (gimp-item-set-name layer1 _"Carved Surface") + (gimp-item-set-name shadow-layer _"Bevel Shadow") + (gimp-item-set-name highlight-layer _"Bevel Highlight") + (gimp-item-set-name cast-shadow-layer _"Cast Shadow") + (gimp-item-set-name inset-layer _"Inset") + + (gimp-brush-delete brush-name) + + (gimp-display-new img) + (gimp-image-undo-enable img) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-carve-it" + _"Stencil C_arve..." + _"Use the specified drawable as a stencil to carve from the specified image." + "Spencer Kimball" + "Spencer Kimball" + "1997" + "GRAY" + SF-IMAGE "Mask image" 0 + SF-DRAWABLE "Mask drawable" 0 + SF-DRAWABLE _"Image to carve" 0 + SF-TOGGLE _"Carve white areas" TRUE +) + +(script-fu-menu-register "script-fu-carve-it" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/chrome-it.scm b/plug-ins/script-fu/scripts/chrome-it.scm new file mode 100644 index 0000000..761ac47 --- /dev/null +++ b/plug-ins/script-fu/scripts/chrome-it.scm @@ -0,0 +1,252 @@ +; CHROME-IT +; State of the art chrome effect for user-specified mask +; This script requires a grayscale image containing a single layer. +; This layer is used as the mask for the SOTA chrome effect + +(define (script-fu-sota-chrome-it mask-img mask-drawable chrome-saturation + chrome-lightness chrome-factor env-map hc cc carve-white) + + (define (set-pt a index x y) + (begin + (aset a (* index 2) x) + (aset a (+ (* index 2) 1) y) + ) + ) + + (define (spline-chrome-it) + (let* ((a (cons-array 18 'double))) + (set-pt a 0 0.0 0.0) + (set-pt a 1 0.125 0.9216) + (set-pt a 2 0.25 0.0902) + (set-pt a 3 0.375 0.9020) + (set-pt a 4 0.5 0.0989) + (set-pt a 5 0.625 0.9549) + (set-pt a 6 0.75 00784) + (set-pt a 7 0.875 0.9412) + (set-pt a 8 1.0 0.1216) + a + ) + ) + + + (define (shadows val) + (/ (* 0.96 val) 2.55) + ) + + (define (midtones val) + (/ val 2.55) + ) + + (define (highlights val) + ; The result is used as "gimp-drawable-color-balance" color parameter + ; and thus must be restricted to -100.0 <= highlights <= 100.0. + (min (/ (* 1.108 val) 2.55) 100.0) + ) + + (define (rval col) + (car col) + ) + + (define (gval col) + (cadr col) + ) + + (define (bval col) + (caddr col) + ) + + (define (sota-scale val scale chrome-factor) + (* (sqrt val) (* scale chrome-factor)) + ) + + (define (copy-layer-chrome-it dest-image dest-drawable source-image source-drawable) + (gimp-selection-all dest-image) + (gimp-drawable-edit-clear dest-drawable) + (gimp-selection-none dest-image) + (gimp-selection-all source-image) + (gimp-edit-copy source-drawable) + (let ( + (floating-sel (car (gimp-edit-paste dest-drawable FALSE))) + ) + (gimp-floating-sel-anchor floating-sel) + ) + ) + + (let* ( + (banding-img (car (gimp-file-load RUN-NONINTERACTIVE env-map env-map))) + (banding-layer (car (gimp-image-get-active-drawable banding-img))) + (banding-height (car (gimp-drawable-height banding-layer))) + (banding-width (car (gimp-drawable-width banding-layer))) + (banding-type (car (gimp-drawable-type banding-layer))) + (width (car (gimp-drawable-width mask-drawable))) + (height (car (gimp-drawable-height mask-drawable))) + (img (car (gimp-image-new width height GRAY))) + (size (min width height)) + (offx1 (sota-scale size 0.33 chrome-factor)) + (offy1 (sota-scale size 0.25 chrome-factor)) + (offx2 (sota-scale size (- 0.33) chrome-factor)) + (offy2 (sota-scale size (- 0.25) chrome-factor)) + (feather (sota-scale size 0.5 chrome-factor)) + (brush-size (sota-scale size 0.5 chrome-factor)) + (brush-name (car (gimp-brush-new "Chrome It"))) + (mask (car (gimp-channel-new img width height "Chrome Stencil" 50 '(0 0 0)))) + (bg-layer (car (gimp-layer-new img width height GRAY-IMAGE _"Background" 100 LAYER-MODE-NORMAL))) + (layer1 (car (gimp-layer-new img banding-width banding-height banding-type _"Layer 1" 100 LAYER-MODE-NORMAL))) + (layer2 (car (gimp-layer-new img width height GRAYA-IMAGE _"Layer 2" 100 LAYER-MODE-DIFFERENCE))) + (layer3 (car (gimp-layer-new img width height GRAYA-IMAGE _"Layer 3" 100 LAYER-MODE-NORMAL))) + (shadow (car (gimp-layer-new img width height GRAYA-IMAGE _"Drop Shadow" 100 LAYER-MODE-NORMAL))) + (mask-fs 0) + (layer-mask 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable img) + + (gimp-image-insert-channel img mask -1 0) + (gimp-image-insert-layer img bg-layer 0 0) + (gimp-image-insert-layer img shadow 0 0) + (gimp-image-insert-layer img layer3 0 0) + (gimp-image-insert-layer img layer2 0 0) + + (gimp-edit-copy mask-drawable) + (set! mask-fs (car (gimp-edit-paste mask FALSE))) + (gimp-floating-sel-anchor mask-fs) + (if (= carve-white FALSE) + (gimp-drawable-invert mask FALSE) + ) + + (gimp-context-set-background '(255 255 255)) + (gimp-selection-none img) + (gimp-drawable-edit-fill layer2 FILL-BACKGROUND) + (gimp-drawable-edit-fill layer3 FILL-BACKGROUND) + (gimp-drawable-edit-clear shadow) + + (gimp-item-set-visible bg-layer FALSE) + (gimp-item-set-visible shadow FALSE) + + (gimp-image-select-item img CHANNEL-OP-REPLACE mask) + (gimp-context-set-background '(0 0 0)) + (gimp-selection-translate img offx1 offy1) + (gimp-selection-feather img feather) + (gimp-drawable-edit-fill layer2 FILL-BACKGROUND) + (gimp-selection-translate img (* 2 offx2) (* 2 offy2)) + (gimp-drawable-edit-fill layer3 FILL-BACKGROUND) + (gimp-selection-none img) + (set! layer2 (car (gimp-image-merge-visible-layers img CLIP-TO-IMAGE))) + (gimp-drawable-invert layer2 FALSE) + + (gimp-image-insert-layer img layer1 0 0) + (copy-layer-chrome-it img layer1 banding-img banding-layer) + (gimp-image-delete banding-img) + (gimp-layer-scale layer1 width height FALSE) + (plug-in-gauss-iir RUN-NONINTERACTIVE img layer1 10 TRUE TRUE) + (gimp-layer-set-opacity layer1 50) + (set! layer1 (car (gimp-image-merge-visible-layers img CLIP-TO-IMAGE))) + (gimp-drawable-curves-spline layer1 HISTOGRAM-VALUE 18 (spline-chrome-it)) + + (set! layer-mask (car (gimp-layer-create-mask layer1 ADD-MASK-BLACK))) + (gimp-layer-add-mask layer1 layer-mask) + (gimp-image-select-item img CHANNEL-OP-REPLACE mask) + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill layer-mask FILL-BACKGROUND) + + (set! layer2 (car (gimp-layer-copy layer1 TRUE))) + (gimp-image-insert-layer img layer2 0 0) + + (gimp-brush-set-shape brush-name BRUSH-GENERATED-CIRCLE) + (gimp-brush-set-spikes brush-name 2) + (gimp-brush-set-hardness brush-name 1.0) + (gimp-brush-set-spacing brush-name 25) + (gimp-brush-set-aspect-ratio brush-name 1) + (gimp-brush-set-angle brush-name 0) + (cond (<= brush-size 17) (gimp-brush-set-radius brush-name (\ brush-size 2)) + (else gimp-brush-set-radius brush-name (\ 19 2))) + (gimp-context-set-brush brush-name) + + (gimp-context-set-foreground '(255 255 255)) + (gimp-drawable-edit-stroke-selection layer-mask) + + (gimp-context-set-background '(0 0 0)) + (gimp-selection-feather img (* feather 1.5)) + (gimp-selection-translate img (* 2.5 offx1) (* 2.5 offy1)) + (gimp-drawable-edit-fill shadow FILL-BACKGROUND) + + (gimp-selection-all img) + (gimp-context-set-pattern "Marble #1") + (gimp-drawable-edit-fill bg-layer FILL-PATTERN) + (gimp-selection-none img) + + (gimp-image-convert-rgb img) + + (gimp-drawable-color-balance layer1 TRANSFER-SHADOWS TRUE + (shadows (rval hc)) + (shadows (gval hc)) + (shadows (bval hc))) + (gimp-drawable-color-balance layer1 TRANSFER-MIDTONES TRUE + (midtones (rval hc)) + (midtones (gval hc)) + (midtones (bval hc))) + (gimp-drawable-color-balance layer1 TRANSFER-HIGHLIGHTS TRUE + (highlights (rval hc)) + (highlights (gval hc)) + (highlights (bval hc))) + + (gimp-drawable-color-balance layer2 TRANSFER-SHADOWS TRUE + (shadows (rval cc)) + (shadows (gval cc)) + (shadows (bval cc))) + (gimp-drawable-color-balance layer2 TRANSFER-MIDTONES TRUE + (midtones (rval cc)) + (midtones (gval cc)) + (midtones (bval cc))) + (gimp-drawable-color-balance layer2 TRANSFER-HIGHLIGHTS TRUE + (highlights (rval cc)) + (highlights (gval cc)) + (highlights (bval cc))) + (gimp-drawable-hue-saturation layer2 HUE-RANGE-ALL + 0.0 + chrome-lightness + chrome-saturation + 0.0) + + (gimp-item-set-visible shadow TRUE) + (gimp-item-set-visible bg-layer TRUE) + + (gimp-item-set-name layer2 _"Chrome") + (gimp-item-set-name layer1 _"Highlight") + + (gimp-image-remove-channel img mask) + + (gimp-brush-delete brush-name) + + (gimp-display-new img) + (gimp-image-undo-enable img) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-sota-chrome-it" + _"Stencil C_hrome..." + _"Add a chrome effect to the selected region (or alpha) using a specified (grayscale) stencil" + "Spencer Kimball" + "Spencer Kimball" + "1997" + "GRAY" + SF-IMAGE "Chrome image" 0 + SF-DRAWABLE "Chrome mask" 0 + SF-ADJUSTMENT _"Chrome saturation" '(-80 -100 100 1 10 0 0) + SF-ADJUSTMENT _"Chrome lightness" '(-47 -100 100 1 10 0 0) + SF-ADJUSTMENT _"Chrome factor" '(0.75 0 1 0.1 0.01 2 0) + SF-FILENAME _"Environment map" + (string-append gimp-data-directory + "/scripts/images/beavis.jpg") + SF-COLOR _"Highlight balance" '(211 95 0) + SF-COLOR _"Chrome balance" "black" + SF-TOGGLE _"Chrome white areas" TRUE +) + +(script-fu-menu-register "script-fu-sota-chrome-it" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/circuit.scm b/plug-ins/script-fu/scripts/circuit.scm new file mode 100644 index 0000000..174a155 --- /dev/null +++ b/plug-ins/script-fu/scripts/circuit.scm @@ -0,0 +1,143 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Circuit board effect +; Copyright (c) 1997 Adrian Likins +; +; Generates what looks a little like the back of an old circuit board. +; Looks even better when gradient-mapp'ed with a suitable gradient. +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-circuit image + drawable + mask-size + seed + remove-bg + keep-selection + separate-layer) + (let* ( + (type (car (gimp-drawable-type-with-alpha drawable))) + (image-width (car (gimp-image-width image))) + (image-height (car (gimp-image-height image))) + (active-selection 0) + (from-selection 0) + (selection-bounds 0) + (select-offset-x 0) + (select-offset-y 0) + (select-width 0) + (select-height 0) + (effect-layer 0) + (active-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-group-start image) + + (gimp-layer-add-alpha drawable) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! active-selection (car (gimp-selection-save image))) + (set! from-selection FALSE)) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))))) + + (set! selection-bounds (gimp-selection-bounds image)) + (set! select-offset-x (cadr selection-bounds)) + (set! select-offset-y (caddr selection-bounds)) + (set! select-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (set! select-height (- (caddr (cddr selection-bounds)) select-offset-y)) + + (if (= separate-layer TRUE) + (begin + (set! effect-layer (car (gimp-layer-new image + select-width + select-height + type + _"Effect layer" + 100 + LAYER-MODE-NORMAL))) + + (gimp-image-insert-layer image effect-layer 0 -1) + (gimp-layer-set-offsets effect-layer select-offset-x select-offset-y) + (gimp-selection-none image) + (gimp-drawable-edit-clear effect-layer) + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-edit-copy drawable) + + (let ((floating-sel (car (gimp-edit-paste effect-layer FALSE)))) + (gimp-floating-sel-anchor floating-sel) + ) + (gimp-image-set-active-layer image effect-layer )) + (set! effect-layer drawable) + ) + (set! active-layer effect-layer) + + (if (= remove-bg TRUE) + (gimp-context-set-foreground '(0 0 0)) + (gimp-context-set-foreground '(14 14 14)) + ) + + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (plug-in-maze RUN-NONINTERACTIVE image active-layer 5 5 TRUE 0 seed 57 1) + (plug-in-oilify RUN-NONINTERACTIVE image active-layer mask-size 0) + (plug-in-edge RUN-NONINTERACTIVE image active-layer 2 1 0) + (if (= type RGBA-IMAGE) + (gimp-drawable-desaturate active-layer DESATURATE-LIGHTNESS)) + + (if (and + (= remove-bg TRUE) + (= separate-layer TRUE)) + (begin + (gimp-image-select-color image CHANNEL-OP-REPLACE active-layer '(0 0 0)) + (gimp-drawable-edit-clear active-layer))) + + (if (= keep-selection FALSE) + (gimp-selection-none image)) + + (gimp-image-remove-channel image active-selection) + (gimp-image-set-active-layer image drawable) + + (gimp-image-undo-group-end image) + + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-circuit" + _"_Circuit..." + _"Fill the selected region (or alpha) with traces like those on a circuit board" + "Adrian Likins <adrian@gimp.org>" + "Adrian Likins" + "10/17/97" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Oilify mask size" '(17 3 50 1 10 0 1) + SF-ADJUSTMENT _"Circuit seed" '(3 1 3000000 1 10 0 1) + SF-TOGGLE _"No background (only for separate layer)" FALSE + SF-TOGGLE _"Keep selection" TRUE + SF-TOGGLE _"Separate layer" TRUE +) + +(script-fu-menu-register "script-fu-circuit" + "<Image>/Filters/Render") diff --git a/plug-ins/script-fu/scripts/clothify.scm b/plug-ins/script-fu/scripts/clothify.scm new file mode 100644 index 0000000..7b6f101 --- /dev/null +++ b/plug-ins/script-fu/scripts/clothify.scm @@ -0,0 +1,68 @@ +; CLOTHIFY version 1.02 +; Gives the current layer in the indicated image a cloth-like texture. +; Process invented by Zach Beane (Xath@irc.gimp.net) +; +; Tim Newsome <drz@froody.bloke.com> 4/11/97 + +(define (script-fu-clothify timg tdrawable bx by azimuth elevation depth) + (let* ( + (width (car (gimp-drawable-width tdrawable))) + (height (car (gimp-drawable-height tdrawable))) + (img (car (gimp-image-new width height RGB))) +; (layer-two (car (gimp-layer-new img width height RGB-IMAGE "Y Dots" 100 LAYER-MODE-MULTIPLY))) + (layer-one (car (gimp-layer-new img width height RGB-IMAGE "X Dots" 100 LAYER-MODE-NORMAL))) + (layer-two 0) + (bump-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable img) + + (gimp-image-insert-layer img layer-one 0 0) + + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill layer-one FILL-BACKGROUND) + + (plug-in-noisify RUN-NONINTERACTIVE img layer-one FALSE 0.7 0.7 0.7 0.7) + + (set! layer-two (car (gimp-layer-copy layer-one 0))) + (gimp-layer-set-mode layer-two LAYER-MODE-MULTIPLY) + (gimp-image-insert-layer img layer-two 0 0) + + (plug-in-gauss-rle RUN-NONINTERACTIVE img layer-one bx TRUE FALSE) + (plug-in-gauss-rle RUN-NONINTERACTIVE img layer-two by FALSE TRUE) + (gimp-image-flatten img) + (set! bump-layer (car (gimp-image-get-active-layer img))) + + (plug-in-c-astretch RUN-NONINTERACTIVE img bump-layer) + (plug-in-noisify RUN-NONINTERACTIVE img bump-layer FALSE 0.2 0.2 0.2 0.2) + + (plug-in-bump-map RUN-NONINTERACTIVE img tdrawable bump-layer azimuth elevation depth 0 0 0 0 FALSE FALSE 0) + (gimp-image-delete img) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + + +(script-fu-register "script-fu-clothify" + _"_Clothify..." + _"Add a cloth-like texture to the selected region (or alpha)" + "Tim Newsome <drz@froody.bloke.com>" + "Tim Newsome" + "4/11/97" + "RGB* GRAY*" + SF-IMAGE "Input image" 0 + SF-DRAWABLE "Input drawable" 0 + SF-ADJUSTMENT _"Blur X" '(9 3 100 1 10 0 1) + SF-ADJUSTMENT _"Blur Y" '(9 3 100 1 10 0 1) + SF-ADJUSTMENT _"Azimuth" '(135 0 360 1 10 1 0) + SF-ADJUSTMENT _"Elevation" '(45 0 90 1 10 1 0) + SF-ADJUSTMENT _"Depth" '(3 1 50 1 10 0 1) +) + +(script-fu-menu-register "script-fu-clothify" + "<Image>/Filters/Artistic") diff --git a/plug-ins/script-fu/scripts/coffee.scm b/plug-ins/script-fu/scripts/coffee.scm new file mode 100644 index 0000000..d72bcb7 --- /dev/null +++ b/plug-ins/script-fu/scripts/coffee.scm @@ -0,0 +1,94 @@ +; Chris Gutteridge (cjg@ecs.soton.ac.uk) +; At ECS Dept, University of Southampton, England. + +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-coffee-stain inImage inLayer inNumber inDark) + (let* ( + (theImage inImage) + (theHeight (car (gimp-image-height theImage))) + (theWidth (car (gimp-image-width theImage))) + (theNumber inNumber) + (theSize (min theWidth theHeight)) + (theStain 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-group-start theImage) + + (while (> theNumber 0) + (set! theNumber (- theNumber 1)) + (set! theStain (car (gimp-layer-new theImage theSize theSize + RGBA-IMAGE _"Stain" 100 + (if (= inDark TRUE) + LAYER-MODE-DARKEN-ONLY LAYER-MODE-NORMAL)))) + + (gimp-image-insert-layer theImage theStain 0 0) + (gimp-selection-all theImage) + (gimp-drawable-edit-clear theStain) + + (let ((blobSize (/ (rand (- theSize 40)) (+ (rand 3) 1)))) + (gimp-image-select-ellipse theImage + CHANNEL-OP-REPLACE + (/ (- theSize blobSize) 2) + (/ (- theSize blobSize) 2) + blobSize blobSize) + ) + + (script-fu-distress-selection theImage theStain + (- (* (+ (rand 15) 1) (+ (rand 15) 1)) 1) + (/ theSize 25) 4 2 TRUE TRUE) + + (gimp-context-set-gradient "Coffee") + + (gimp-drawable-edit-gradient-fill theStain + GRADIENT-SHAPEBURST-DIMPLED 0 + FALSE 0 0 + TRUE + 0 0 0 0) + + (gimp-layer-set-offsets theStain + (- (rand theWidth) (/ theSize 2)) + (- (rand theHeight) (/ theSize 2))) + ) + + (gimp-selection-none theImage) + + (gimp-image-undo-group-end theImage) + + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +; Register the function with GIMP: + +(script-fu-register "script-fu-coffee-stain" + _"_Coffee Stain..." + _"Add realistic looking coffee stains to the image" + "Chris Gutteridge" + "1998, Chris Gutteridge / ECS dept, University of Southampton, England." + "25th April 1998" + "RGB*" + SF-IMAGE "The image" 0 + SF-DRAWABLE "The layer" 0 + SF-ADJUSTMENT _"Stains" '(3 1 10 1 1 0 0) + SF-TOGGLE _"Darken only" TRUE +) + +(script-fu-menu-register "script-fu-coffee-stain" "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/contactsheet.scm b/plug-ins/script-fu/scripts/contactsheet.scm new file mode 100644 index 0000000..5f7520e --- /dev/null +++ b/plug-ins/script-fu/scripts/contactsheet.scm @@ -0,0 +1,337 @@ +; "Contact Sheet" v1.2 September 5, 2007 +; by Kevin Cozens <kcozens@interlog.com> +; +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; Version 1.0 (July 27, 2004) +; Created +; +; Version 1.1 (September 2, 2004) +; Added ability to select sheet size, set font used for sheet and image +; +; Version 1.2 (September 5, 2007) +; Preserve aspect ratio of original image. Center thumbnail in the area +; allowed for the thumbnail. Added disable/enable of undo operations. +; Added 1600x1200 sheet size. + +(define (script-fu-contactsheet dir sheet-size + title-font legend-font text-color bg-color) + + (define (init-sheet-data size) + (let ( + (sheet-w 0) + (sheet-h 0) + (thumb-w 0) + (thumb-h 0) + (border-x 0) ;Space between rows and at top and bottom of thumbnails + (border-y 0) ;Space between columns and at left and right of thumbnails + (off-x 0) ; Additional X shift to properly center a row of thumbnails + (off-y 0) ; Additional Y shift to properly center rows of thumbnails + (count 0) + ) + + (case size + ((0) (set! sheet-w 640) + (set! sheet-h 480) + (set! thumb-w 90) + (set! thumb-h 68) + (set! border-x 32) + (set! border-y 23) + (set! off-x -1) + (set! off-y 0) + (set! count 4) + ) + + ((1) (set! sheet-w 800) + (set! sheet-h 600) + (set! thumb-w 119) + (set! thumb-h 90) + (set! border-x 34) + (set! border-y 25) + (set! off-x 0) + (set! off-y 0) + (set! count 4) + ) + + ((2) (set! sheet-w 1024) + (set! sheet-h 768) + (set! thumb-w 133) + (set! thumb-h 100) + (set! border-x 32) + (set! border-y 24) + (set! off-x 1) + (set! off-y 0) + (set! count 5) + ) + + ((3) (set! sheet-w 1280) + (set! sheet-h 1024) + (set! thumb-w 133) + (set! thumb-h 100) + (set! border-x 24) + (set! border-y 25) + (set! off-x 0) + (set! off-y 0) + (set! count 7) + ) + + ((4) (set! sheet-w 1600) + (set! sheet-h 1200) + (set! thumb-w 120) + (set! thumb-h 90) + (set! border-x 36) + (set! border-y 25) + (set! off-x 2) + (set! off-y 0) + (set! count 9) + ) + ) + + (list sheet-w sheet-h thumb-w thumb-h border-x border-y off-x off-y count) + ) + ) + + (define (init-sheet-img img num img-width border-y off-y) + (let* ( + (text-layer 0) + (text-width 0) + (text-height 0) + ) + (gimp-selection-all img) + (gimp-drawable-fill (car (gimp-image-get-active-layer img)) + FILL-BACKGROUND) + (gimp-selection-none img) + (set! text-layer (car (gimp-text-fontname img -1 0 0 + (string-append _"Contact Sheet " + (number->string num) + _" for directory " dir) + 0 TRUE 14 PIXELS title-font))) + (set! text-width (car (gimp-drawable-width text-layer))) + (set! text-height (car (gimp-drawable-height text-layer))) + (gimp-layer-set-offsets text-layer + (/ (- img-width text-width) 2) + (/ (- (+ border-y off-y) text-height) 2) + ) + (gimp-image-merge-visible-layers img CLIP-TO-IMAGE) + ) + ) + + (define (make-thumbnail-size img thumb-w thumb-h) + (let* ( + (file-height (car (gimp-image-height img))) + (file-width (car (gimp-image-width img))) + (aspect-ratio (/ file-width file-height)) + ) + + ;Preserve the aspect ratio of the original image + (if (> file-width file-height) + (set! thumb-h (/ thumb-w aspect-ratio)) + (set! thumb-w (* thumb-h aspect-ratio)) + ) + + (gimp-image-scale img thumb-w thumb-h) + ) + ) + + (let* ( + (dir-stream (dir-open-stream dir)) + (sheet-num 1) + (img-count 0) + (pos-x 0) + (pos-y 0) + + (sheet-data 0) + (sheet-width 0) + (sheet-height 0) + (thumb-w 0) + (thumb-h 0) + (border-x 0) + (border-y 0) + (off-x 0) + (off-y 0) + (max-x 0) + (max-y 0) + + (sheet-img 0) + (sheet-layer 0) + + (new-img 0) + (file 0) + (file-path 0) + (tmp-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + (gimp-context-set-foreground text-color) + (gimp-context-set-background bg-color) + + (set! sheet-data (init-sheet-data sheet-size)) + (set! sheet-width (car sheet-data)) + (set! sheet-height (cadr sheet-data)) + (set! sheet-data (cddr sheet-data)) + (set! thumb-w (car sheet-data)) + (set! thumb-h (cadr sheet-data)) + (set! sheet-data (cddr sheet-data)) + (set! border-x (car sheet-data)) + (set! border-y (cadr sheet-data)) + (set! sheet-data (cddr sheet-data)) + (set! off-x (car sheet-data)) + (set! off-y (cadr sheet-data)) + (set! max-x (caddr sheet-data)) + (set! max-y max-x) + + (set! sheet-img (car (gimp-image-new sheet-width sheet-height RGB))) + + (gimp-image-undo-disable sheet-img) + + (set! sheet-layer (car (gimp-layer-new sheet-img sheet-width sheet-height + RGB-IMAGE "Background" + 100 LAYER-MODE-NORMAL))) + (gimp-image-insert-layer sheet-img sheet-layer 0 0) + + (init-sheet-img sheet-img sheet-num sheet-width border-y off-y) + + (if (not dir-stream) + (gimp-message (string-append _"Unable to open directory " dir)) + (begin + (do + ( (file (dir-read-entry dir-stream) (dir-read-entry dir-stream)) ) + ( (eof-object? file) ) + + (set! file-path (string-append dir DIR-SEPARATOR file)) + (if (and (not (re-match "index.*" file)) + (= (file-type file-path) FILE-TYPE-FILE) + ) + (catch () + (set! new-img + (car (gimp-file-load RUN-NONINTERACTIVE file-path file))) + + (make-thumbnail-size new-img thumb-w thumb-h) + + (if (> (car (gimp-image-get-layers new-img)) 1) + (gimp-image-flatten new-img) + ) + (set! tmp-layer (car (gimp-layer-new-from-drawable + (car (gimp-image-get-active-drawable new-img)) + sheet-img))) + + (gimp-image-insert-layer sheet-img tmp-layer 0 0) + + ;Move thumbnail in to position and center it in area available. + (gimp-layer-set-offsets tmp-layer + (+ border-x off-x (* pos-x (+ thumb-w border-x)) + (/ (- thumb-w (car (gimp-image-width new-img))) 2) + ) + (+ border-y off-y (* pos-y (+ thumb-h border-y)) + (/ (- thumb-h (car (gimp-image-height new-img))) 2) + ) + ) + + (gimp-image-delete new-img) + + (set! tmp-layer (car (gimp-text-fontname sheet-img -1 0 0 file + 0 TRUE 12 PIXELS legend-font))) + (gimp-layer-set-offsets tmp-layer + (+ border-x off-x (* pos-x (+ thumb-w border-x)) + (/ (- thumb-w (car (gimp-drawable-width tmp-layer))) 2)) + (+ border-y off-y (* pos-y (+ thumb-h border-y)) thumb-h 6) + ) + + (set! img-count (+ img-count 1)) + + (set! pos-x (+ pos-x 1)) + (if (> pos-x max-x) + (begin + (set! pos-x 0) + (set! pos-y (+ pos-y 1)) + (if (> pos-y max-y) + (begin + (set! pos-y 0) + (set! sheet-layer (car (gimp-image-flatten sheet-img))) + (gimp-file-save + RUN-NONINTERACTIVE + sheet-img + sheet-layer + (string-append dir DIR-SEPARATOR + "index" (number->string sheet-num) ".jpg") + (string-append + "index" (number->string sheet-num) ".jpg") + ) + + (set! sheet-num (+ sheet-num 1)) + (init-sheet-img sheet-img sheet-num sheet-width + border-y off-y) + (set! img-count 0) + ) + ) + ) + ) + ) + ) + ) + + (dir-close-stream dir-stream) + + (if (> img-count 0) + (begin + (set! sheet-layer (car (gimp-image-flatten sheet-img))) + (gimp-file-save + RUN-NONINTERACTIVE + sheet-img + sheet-layer + (string-append dir DIR-SEPARATOR + "index" (number->string sheet-num) ".jpg") + (string-append "index" (number->string sheet-num) ".jpg") + ) + ) + ) + ) + + (gimp-image-undo-enable sheet-img) + (gimp-image-delete sheet-img) + + (display (string-append _"Created " (number->string sheet-num) + _" contact sheets from a total of " + (number->string img-count) _" images")) + (newline) + ) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-contactsheet" + _"_Contact Sheet..." + _"Create a series of images containing thumbnail sized versions of all of the images in a specified directory." + "Kevin Cozens <kcozens@interlog.com>" + "Kevin Cozens" + "July 19, 2004" + "" + SF-DIRNAME _"Images Directory" "/tmp/test" + SF-OPTION _"Sheet size" '("640 x 480" + "800 x 600" + "1024 x 768" + "1280 x 1024" + "1600 x 1200") + SF-FONT _"Title font" "Sans Bold Italic" + SF-FONT _"Legend font" "Sans Bold" + SF-COLOR _"Text color" "white" + SF-COLOR _"Background color" "black" +) + +(script-fu-menu-register "script-fu-contactsheet" "<Image>/Filters/Combine") diff --git a/plug-ins/script-fu/scripts/copy-visible.scm b/plug-ins/script-fu/scripts/copy-visible.scm new file mode 100644 index 0000000..942793c --- /dev/null +++ b/plug-ins/script-fu/scripts/copy-visible.scm @@ -0,0 +1,49 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; "Copy Visible" -- copy the visible selection so that it can be pasted easily +; Copyright (C) 2004 Raphaël Quinet, Adrian Likins, Sven Neumann +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; 2004-04-14 This script was almost rewritten from scratch +; by Raphaël Quinet <raphael@gimp.org> +; see also http://bugzilla.gnome.org/show_bug.cgi?id=139989 +; +; The code is new but the API is the same as in the previous version: +; "Copy Visible" version 0.11 01/24/98 +; by Adrian Likins <adrian@gimp.org> +; _heavily_ based on: +; cyn-merge.scm version 0.02 10/10/97 +; Copyright (C) 1997 Sven Neumann (neumanns@uni-duesseldorf.de) +; +; Removed all code and made it a backward-compat wrapper around +; (gimp-edit-copy-visible) +; 2004-12-12 Michael Natterer <mitch@gimp.org> +; + +(define (script-fu-copy-visible image drawable) + (gimp-edit-copy-visible image) +) + +(script-fu-register "script-fu-copy-visible" + "Copy Visible" + "This procedure is deprecated! Use \'gimp-edit-copy-visible\' instead." + "" + "" + "" + "RGB* INDEXED* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 +) diff --git a/plug-ins/script-fu/scripts/difference-clouds.scm b/plug-ins/script-fu/scripts/difference-clouds.scm new file mode 100644 index 0000000..15b8fc8 --- /dev/null +++ b/plug-ins/script-fu/scripts/difference-clouds.scm @@ -0,0 +1,80 @@ +; Plugin for the GNU Image Manipulation Program +; Copyright (C) 2006 Martin Nordholts +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; Renders Difference Clouds onto a layer, i.e. solid noise merged down with the +; Difference Mode +; + +(define (script-fu-difference-clouds image + drawable) + + (let* ((draw-offset-x (car (gimp-drawable-offsets drawable))) + (draw-offset-y (cadr (gimp-drawable-offsets drawable))) + (has-sel (car (gimp-drawable-mask-intersect drawable))) + (sel-offset-x (cadr (gimp-drawable-mask-intersect drawable))) + (sel-offset-y (caddr (gimp-drawable-mask-intersect drawable))) + (width (cadddr (gimp-drawable-mask-intersect drawable))) + (height (caddr (cddr (gimp-drawable-mask-intersect drawable)))) + (type (car (gimp-drawable-type-with-alpha drawable))) + (diff-clouds -1) + (offset-x 0) + (offset-y 0) + ) + + (gimp-image-undo-group-start image) + + ; Create the cloud layer + (set! diff-clouds (car (gimp-layer-new image width height type + "Clouds" 100 LAYER-MODE-DIFFERENCE))) + + ; Add the cloud layer above the current layer + (gimp-image-insert-layer image diff-clouds 0 -1) + + ; Clear the layer (so there are no noise in it) + (gimp-drawable-fill diff-clouds FILL-TRANSPARENT) + + ; Selections are relative to the drawable; adjust the final offset + (set! offset-x (+ draw-offset-x sel-offset-x)) + (set! offset-y (+ draw-offset-y sel-offset-y)) + + ; Offset the clouds layer + (if (gimp-item-is-layer drawable) + (gimp-item-transform-translate diff-clouds offset-x offset-y)) + + ; Show the solid noise dialog + (plug-in-solid-noise SF-RUN-MODE image diff-clouds 0 0 0 1 4.0 4.0) + + ; Merge the clouds layer with the layer below + (gimp-image-merge-down image diff-clouds EXPAND-AS-NECESSARY) + + (gimp-image-undo-group-end image) + + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-difference-clouds" + _"_Difference Clouds..." + _"Solid noise applied with Difference layer mode" + "Martin Nordholts <enselic@hotmail.com>" + "Martin Nordholts" + "2006/10/25" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0) + +(script-fu-menu-register "script-fu-difference-clouds" + "<Image>/Filters/Render/Noise") diff --git a/plug-ins/script-fu/scripts/distress-selection.scm b/plug-ins/script-fu/scripts/distress-selection.scm new file mode 100644 index 0000000..ef87b79 --- /dev/null +++ b/plug-ins/script-fu/scripts/distress-selection.scm @@ -0,0 +1,122 @@ +; +; distress selection +; +; +; Chris Gutteridge (cjg@ecs.soton.ac.uk) +; At ECS Dept, University of Southampton, England. + +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +; Define the function: + +(define (script-fu-distress-selection inImage + inDrawable + inThreshold + inSpread + inGranu + inSmooth + inSmoothH + inSmoothV) + + (let ( + (theImage inImage) + (theWidth (car (gimp-image-width inImage))) + (theHeight (car (gimp-image-height inImage))) + (theLayer 0) + (theMode (car (gimp-image-base-type inImage))) + (prevLayer (car (gimp-image-get-active-layer inImage))) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + (gimp-image-undo-group-start theImage) + + (if (= theMode GRAY) + (set! theMode GRAYA-IMAGE) + (set! theMode RGBA-IMAGE) + ) + (set! theLayer (car (gimp-layer-new theImage + theWidth + theHeight + theMode + "Distress Scratch Layer" + 100 + LAYER-MODE-NORMAL))) + + (gimp-image-insert-layer theImage theLayer 0 0) + + (if (= FALSE (car (gimp-selection-is-empty theImage))) + (gimp-drawable-edit-fill theLayer FILL-BACKGROUND) + ) + + (gimp-selection-invert theImage) + + (if (= FALSE (car (gimp-selection-is-empty theImage))) + (gimp-drawable-edit-clear theLayer) + ) + + (gimp-selection-invert theImage) + (gimp-selection-none inImage) + + (gimp-layer-scale theLayer + (/ theWidth inGranu) + (/ theHeight inGranu) + TRUE) + + (plug-in-spread RUN-NONINTERACTIVE + theImage + theLayer + inSpread + inSpread) + + (plug-in-gauss-iir RUN-NONINTERACTIVE + theImage theLayer inSmooth inSmoothH inSmoothV) + (gimp-layer-scale theLayer theWidth theHeight TRUE) + (plug-in-threshold-alpha RUN-NONINTERACTIVE theImage theLayer inThreshold) + (plug-in-gauss-iir RUN-NONINTERACTIVE theImage theLayer 1 TRUE TRUE) + (gimp-image-select-item inImage CHANNEL-OP-REPLACE theLayer) + (gimp-image-remove-layer theImage theLayer) + (if (and (= (car (gimp-item-is-channel inDrawable)) TRUE) + (= (car (gimp-item-is-layer-mask inDrawable)) FALSE)) + (gimp-image-set-active-channel theImage inDrawable) + ) + (gimp-image-undo-group-end theImage) + + (gimp-image-set-active-layer theImage prevLayer) + + (gimp-displays-flush) + (gimp-context-pop) + ) +) + + +(script-fu-register "script-fu-distress-selection" + _"_Distort..." + _"Distress the selection" + "Chris Gutteridge" + "1998, Chris Gutteridge / ECS dept, University of Southampton, England." + "23rd April 1998" + "RGB*,GRAY*" + SF-IMAGE "The image" 0 + SF-DRAWABLE "The layer" 0 + SF-ADJUSTMENT _"_Threshold (bigger 1<-->254 smaller)" '(127 1 254 1 10 0 0) + SF-ADJUSTMENT _"_Spread" '(8 0 1000 1 10 0 1) + SF-ADJUSTMENT _"_Granularity (1 is low)" '(4 1 25 1 10 0 1) + SF-ADJUSTMENT _"S_mooth" '(2 1 150 1 10 0 1) + SF-TOGGLE _"Smooth hor_izontally" TRUE + SF-TOGGLE _"Smooth _vertically" TRUE +) + +(script-fu-menu-register "script-fu-distress-selection" + "<Image>/Select/Modify") diff --git a/plug-ins/script-fu/scripts/drop-shadow.scm b/plug-ins/script-fu/scripts/drop-shadow.scm new file mode 100644 index 0000000..c1b243a --- /dev/null +++ b/plug-ins/script-fu/scripts/drop-shadow.scm @@ -0,0 +1,187 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; drop-shadow.scm version 1.05 2011/4/21 +; +; CHANGE-LOG: +; 1.00 - initial release +; 1.01 - fixed the problem with a remaining copy of the selection +; 1.02 - some code cleanup, no real changes +; 1.03 - can't call gimp-drawable-edit-fill until layer is added to image! +; 1.04 +; 1.05 - replaced deprecated function calls with new ones for 2.8 +; +; Copyright (C) 1997-1999 Sven Neumann <sven@gimp.org> +; +; +; Adds a drop-shadow of the current selection or alpha-channel. +; +; This script is derived from my script add-shadow, which has become +; obsolete now. Thanks to Andrew Donkin (ard@cs.waikato.ac.nz) for his +; idea to add alpha-support to add-shadow. + + +(define (script-fu-drop-shadow image + drawable + shadow-transl-x + shadow-transl-y + shadow-blur + shadow-color + shadow-opacity + allow-resize) + (let* ( + (shadow-blur (max shadow-blur 0)) + (shadow-opacity (min shadow-opacity 100)) + (shadow-opacity (max shadow-opacity 0)) + (type (car (gimp-drawable-type-with-alpha drawable))) + (image-width (car (gimp-image-width image))) + (image-height (car (gimp-image-height image))) + (from-selection 0) + (active-selection 0) + (shadow-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-set-active-layer image drawable) + + (gimp-image-undo-group-start image) + + (gimp-layer-add-alpha drawable) + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! from-selection FALSE)) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))))) + + (let* ((selection-bounds (gimp-selection-bounds image)) + (select-offset-x (cadr selection-bounds)) + (select-offset-y (caddr selection-bounds)) + (select-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (select-height (- (caddr (cddr selection-bounds)) select-offset-y)) + + (shadow-width (+ select-width (* 2 shadow-blur))) + (shadow-height (+ select-height (* 2 shadow-blur))) + + (shadow-offset-x (- select-offset-x shadow-blur)) + (shadow-offset-y (- select-offset-y shadow-blur))) + + (if (= allow-resize TRUE) + (let* ((new-image-width image-width) + (new-image-height image-height) + (image-offset-x 0) + (image-offset-y 0)) + + (if (< (+ shadow-offset-x shadow-transl-x) 0) + (begin + (set! image-offset-x (- 0 (+ shadow-offset-x + shadow-transl-x))) + (set! shadow-offset-x (- 0 shadow-transl-x)) + (set! new-image-width (+ new-image-width image-offset-x)))) + + (if (< (+ shadow-offset-y shadow-transl-y) 0) + (begin + (set! image-offset-y (- 0 (+ shadow-offset-y + shadow-transl-y))) + (set! shadow-offset-y (- 0 shadow-transl-y)) + (set! new-image-height (+ new-image-height image-offset-y)))) + + (if (> (+ (+ shadow-width shadow-offset-x) shadow-transl-x) + new-image-width) + (set! new-image-width + (+ (+ shadow-width shadow-offset-x) shadow-transl-x))) + + (if (> (+ (+ shadow-height shadow-offset-y) shadow-transl-y) + new-image-height) + (set! new-image-height + (+ (+ shadow-height shadow-offset-y) shadow-transl-y))) + + (gimp-image-resize image + new-image-width + new-image-height + image-offset-x + image-offset-y) + ) + ) + + (set! shadow-layer (car (gimp-layer-new image + shadow-width + shadow-height + type + "Drop Shadow" + shadow-opacity + LAYER-MODE-NORMAL))) + (gimp-image-set-active-layer image drawable) + (gimp-image-insert-layer image shadow-layer 0 -1) + (gimp-layer-set-offsets shadow-layer + shadow-offset-x + shadow-offset-y)) + + (gimp-drawable-fill shadow-layer FILL-TRANSPARENT) + (gimp-context-set-background shadow-color) + (gimp-drawable-edit-fill shadow-layer FILL-BACKGROUND) + (gimp-selection-none image) + (gimp-layer-set-lock-alpha shadow-layer FALSE) + (if (>= shadow-blur 1.0) (plug-in-gauss-rle RUN-NONINTERACTIVE + image + shadow-layer + shadow-blur + TRUE + TRUE)) + (gimp-item-transform-translate shadow-layer shadow-transl-x shadow-transl-y) + + (if (= from-selection TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-drawable-edit-clear shadow-layer) + (gimp-image-remove-channel image active-selection))) + + (if (and + (= (car (gimp-layer-is-floating-sel drawable)) 0) + (= from-selection FALSE)) + (gimp-image-raise-item image drawable)) + + (gimp-image-set-active-layer image drawable) + (gimp-image-undo-group-end image) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-drop-shadow" + _"_Drop Shadow (legacy)..." + _"Add a drop shadow to the selected region (or alpha)" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "1999/12/21" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Offset X" '(4 -4096 4096 1 10 0 1) + SF-ADJUSTMENT _"Offset Y" '(4 -4096 4096 1 10 0 1) + SF-ADJUSTMENT _"Blur radius" '(15 0 1024 1 10 0 1) + SF-COLOR _"Color" "black" + SF-ADJUSTMENT _"Opacity" '(60 0 100 1 10 0 0) + SF-TOGGLE _"Allow resizing" TRUE +) + +(script-fu-menu-register "script-fu-drop-shadow" + "<Image>/Filters/Light and Shadow/Shadow") diff --git a/plug-ins/script-fu/scripts/erase-rows.scm b/plug-ins/script-fu/scripts/erase-rows.scm new file mode 100644 index 0000000..4ae4c77 --- /dev/null +++ b/plug-ins/script-fu/scripts/erase-rows.scm @@ -0,0 +1,71 @@ +(define (script-fu-erase-rows img drawable orientation which type) + (script-fu-erase-nth-rows img drawable orientation which type 2) +) + +(define (script-fu-erase-nth-rows img drawable orientation offset type nth) + (let* ( + (width (car (gimp-drawable-width drawable))) + (height (car (gimp-drawable-height drawable))) + (position-x (car (gimp-drawable-offsets drawable))) + (position-y (cadr (gimp-drawable-offsets drawable))) + ) + + (gimp-context-push) + (gimp-context-set-paint-mode LAYER-MODE-NORMAL) + (gimp-context-set-opacity 100.0) + (gimp-context-set-feather FALSE) + (gimp-image-undo-group-start img) + (letrec ((loop (lambda (i max) + (if (< i max) + (begin + (if (= orientation 0) + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE position-x (+ i position-y) width 1) + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE (+ i position-x) position-y 1 height)) + (if (= type 0) + (gimp-drawable-edit-clear drawable) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND)) + (loop (+ i nth) max)))))) + (loop offset + (if (= orientation 0) + height + width) + ) + ) + (gimp-selection-none img) + (gimp-image-undo-group-end img) + (gimp-context-pop) + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-erase-nth-rows" + _"_Erase Every Nth Row..." + _"Erase every nth row or column" + "Federico Mena Quintero, Nikc M. (Altered)" + "Federico Mena Quintero" + "June 1997, February 2020" + "RGB* GRAY* INDEXED*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-OPTION _"Rows/cols" '(_"Rows" _"Columns") + SF-ADJUSTMENT "Offset" '(0 0 1024 1 10 0 SF-SPINNER) + SF-OPTION _"Erase/fill" '(_"Erase" _"Fill with BG") + SF-ADJUSTMENT "Skip by" '(1 1 1024 1 10 0 SF-SPINNER) +) + +(script-fu-register "script-fu-erase-rows" + _"_Erase Every Other Row..." + _"Erase every other row or column" + "Federico Mena Quintero" + "Federico Mena Quintero" + "June 1997" + "RGB* GRAY* INDEXED*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-OPTION _"Rows/cols" '(_"Rows" _"Columns") + SF-OPTION _"Even/odd" '(_"Even" _"Odd") + SF-OPTION _"Erase/fill" '(_"Erase" _"Fill with BG") +) + +; (script-fu-menu-register "script-fu-erase-rows" +; "<Image>/Filters/Distorts") diff --git a/plug-ins/script-fu/scripts/font-map.scm b/plug-ins/script-fu/scripts/font-map.scm new file mode 100644 index 0000000..7481d28 --- /dev/null +++ b/plug-ins/script-fu/scripts/font-map.scm @@ -0,0 +1,168 @@ +;; font-select +;; Spencer Kimball + +(define (script-fu-font-map text + use-name + labels + font-filter + font-size + border + colors) + + (define (max-font-width text use-name list-cnt list font-size) + (let* ((count 0) + (width 0) + (maxwidth 0) + (font "") + (extents '())) + (while (< count list-cnt) + (set! font (car list)) + + (if (= use-name TRUE) + (set! text font)) + (set! extents (gimp-text-get-extents-fontname text + font-size PIXELS + font)) + (set! width (car extents)) + (if (> width maxwidth) + (set! maxwidth width)) + + (set! list (cdr list)) + (set! count (+ count 1)) + ) + + maxwidth + ) + ) + + (define (max-font-height text use-name list-cnt list font-size) + (let* ((count 0) + (height 0) + (maxheight 0) + (font "") + (extents '())) + (while (< count list-cnt) + (set! font (car list)) + + (if (= use-name TRUE) + (set! text font) + ) + (set! extents (gimp-text-get-extents-fontname text + font-size PIXELS + font)) + (set! height (cadr extents)) + (if (> height maxheight) + (set! maxheight height) + ) + + (set! list (cdr list)) + (set! count (+ count 1)) + ) + + maxheight + ) + ) + + (let* ( + (font-data (gimp-fonts-get-list font-filter)) + (font-list (cadr font-data)) + (num-fonts (car font-data)) + (label-size (/ font-size 2)) + (border (+ border (* labels (/ label-size 2)))) + (y border) + (maxheight (max-font-height text use-name num-fonts font-list font-size)) + (maxwidth (max-font-width text use-name num-fonts font-list font-size)) + (width (+ maxwidth (* 2 border))) + (height (+ (+ (* maxheight num-fonts) (* 2 border)) + (* labels (* label-size num-fonts)))) + (img (car (gimp-image-new width height (if (= colors 0) + GRAY RGB)))) + (drawable (car (gimp-layer-new img width height (if (= colors 0) + GRAY-IMAGE RGB-IMAGE) + "Background" 100 LAYER-MODE-NORMAL))) + (count 0) + (font "") + ) + + (gimp-context-push) + + (gimp-image-undo-disable img) + + (if (= colors 0) + (begin + (gimp-context-set-background '(255 255 255)) + (gimp-context-set-foreground '(0 0 0)))) + + (gimp-image-insert-layer img drawable 0 0) + (gimp-drawable-edit-clear drawable) + + (if (= labels TRUE) + (begin + (set! drawable (car (gimp-layer-new img width height + (if (= colors 0) + GRAYA-IMAGE RGBA-IMAGE) + "Labels" 100 LAYER-MODE-NORMAL))) + (gimp-image-insert-layer img drawable 0 -1))) + (gimp-drawable-edit-clear drawable) + + (while (< count num-fonts) + (set! font (car font-list)) + + (if (= use-name TRUE) + (set! text font)) + + (gimp-text-fontname img -1 + border + y + text + 0 TRUE font-size PIXELS + font) + + (set! y (+ y maxheight)) + + (if (= labels TRUE) + (begin + (gimp-floating-sel-anchor (car (gimp-text-fontname img drawable + (- border + (/ label-size 2)) + (- y + (/ label-size 2)) + font + 0 TRUE + label-size PIXELS + "Sans"))) + (set! y (+ y label-size)) + ) + ) + + (set! font-list (cdr font-list)) + (set! count (+ count 1)) + ) + + (gimp-image-set-active-layer img drawable) + + (gimp-image-undo-enable img) + (gimp-display-new img) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-font-map" + _"Render _Font Map..." + _"Create an image filled with previews of fonts matching a fontname filter" + "Spencer Kimball" + "Spencer Kimball" + "1997" + "" + SF-STRING _"_Text" "How quickly daft jumping zebras vex." + SF-TOGGLE _"Use font _name as text" FALSE + SF-TOGGLE _"_Labels" TRUE + SF-STRING _"_Filter (regexp)" "Sans" + SF-ADJUSTMENT _"Font _size (pixels)" '(32 2 1000 1 10 0 1) + SF-ADJUSTMENT _"_Border (pixels)" '(10 0 200 1 10 0 1) + SF-OPTION _"_Color scheme" '(_"Black on white" _"Active colors") +) + +(script-fu-menu-register "script-fu-font-map" + "<Fonts>") diff --git a/plug-ins/script-fu/scripts/fuzzyborder.scm b/plug-ins/script-fu/scripts/fuzzyborder.scm new file mode 100644 index 0000000..9c3ddbe --- /dev/null +++ b/plug-ins/script-fu/scripts/fuzzyborder.scm @@ -0,0 +1,168 @@ +; +; fuzzy-border +; +; Do a cool fade to a given color at the border of an image (optional shadow) +; Will make image RGB if it isn't already. +; +; Chris Gutteridge (cjg@ecs.soton.ac.uk) +; At ECS Dept, University of Southampton, England. + +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +; Define the function: + +(define (script-fu-fuzzy-border inImage + inLayer + inColor + inSize + inBlur + inGranu + inShadow + inShadWeight + inCopy + inFlatten + ) + + (define (chris-color-edge inImage inLayer inColor inSize) + (gimp-selection-all inImage) + (gimp-selection-shrink inImage inSize) + (gimp-selection-invert inImage) + (gimp-context-set-background inColor) + (gimp-drawable-edit-fill inLayer FILL-BACKGROUND) + (gimp-selection-none inImage) + ) + + (let ( + (theWidth (car (gimp-image-width inImage))) + (theHeight (car (gimp-image-height inImage))) + (theImage (if (= inCopy TRUE) (car (gimp-image-duplicate inImage)) + inImage)) + (theLayer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (if (= inCopy TRUE) + (gimp-image-undo-disable theImage) + (gimp-image-undo-group-start theImage) + ) + + (gimp-selection-all theImage) + + (if (> (car (gimp-drawable-type inLayer)) 1) + (gimp-image-convert-rgb theImage) + ) + + (set! theLayer (car (gimp-layer-new theImage + theWidth + theHeight + RGBA-IMAGE + "layer 1" + 100 + LAYER-MODE-NORMAL))) + + (gimp-image-insert-layer theImage theLayer 0 0) + + + (gimp-drawable-edit-clear theLayer) + (chris-color-edge theImage theLayer inColor inSize) + + (gimp-layer-scale theLayer + (/ theWidth inGranu) + (/ theHeight inGranu) + TRUE) + + (plug-in-spread RUN-NONINTERACTIVE + theImage + theLayer + (/ inSize inGranu) + (/ inSize inGranu)) + (chris-color-edge theImage theLayer inColor 1) + (gimp-layer-scale theLayer theWidth theHeight TRUE) + + (gimp-image-select-item theImage CHANNEL-OP-REPLACE theLayer) + (gimp-selection-invert theImage) + (gimp-drawable-edit-clear theLayer) + (gimp-selection-invert theImage) + (gimp-drawable-edit-clear theLayer) + (gimp-context-set-background inColor) + (gimp-drawable-edit-fill theLayer FILL-BACKGROUND) + (gimp-selection-none theImage) + (chris-color-edge theImage theLayer inColor 1) + + (if (= inBlur TRUE) + (plug-in-gauss-rle RUN-NONINTERACTIVE + theImage theLayer inSize TRUE TRUE) + ) + (if (= inShadow TRUE) + (begin + (gimp-image-insert-layer theImage + (car (gimp-layer-copy theLayer FALSE)) 0 -1) + (gimp-layer-scale theLayer + (- theWidth inSize) (- theHeight inSize) TRUE) + (gimp-drawable-desaturate theLayer DESATURATE-LIGHTNESS) + (gimp-drawable-brightness-contrast theLayer 0.5 0.5) + (gimp-drawable-invert theLayer FALSE) + (gimp-layer-resize theLayer + theWidth + theHeight + (/ inSize 2) + (/ inSize 2)) + (plug-in-gauss-rle RUN-NONINTERACTIVE + theImage + theLayer + (/ inSize 2) + TRUE + TRUE) + (gimp-layer-set-opacity theLayer inShadWeight) + ) + ) + (if (= inFlatten TRUE) + (gimp-image-flatten theImage) + ) + (if (= inCopy TRUE) + (begin (gimp-image-clean-all theImage) + (gimp-display-new theImage) + (gimp-image-undo-enable theImage) + ) + (gimp-image-undo-group-end theImage) + ) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-fuzzy-border" + _"_Fuzzy Border..." + _"Add a jagged, fuzzy border to an image" + "Chris Gutteridge" + "1998, Chris Gutteridge / ECS dept, University of Southampton, England." + "3rd April 1998" + "RGB* GRAY*" + SF-IMAGE "The image" 0 + SF-DRAWABLE "The layer" 0 + SF-COLOR _"Color" "white" + SF-ADJUSTMENT _"Border size" '(16 1 300 1 10 0 1) + SF-TOGGLE _"Blur border" TRUE + SF-ADJUSTMENT _"Granularity (1 is Low)" '(4 1 16 0.25 5 2 0) + SF-TOGGLE _"Add shadow" FALSE + SF-ADJUSTMENT _"Shadow weight (%)" '(100 0 100 1 10 0 0) + SF-TOGGLE _"Work on copy" TRUE + SF-TOGGLE _"Flatten image" TRUE +) + +(script-fu-menu-register "script-fu-fuzzy-border" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/gimp-online.scm b/plug-ins/script-fu/scripts/gimp-online.scm new file mode 100644 index 0000000..69afd10 --- /dev/null +++ b/plug-ins/script-fu/scripts/gimp-online.scm @@ -0,0 +1,293 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; gimp-online.scm +; Copyright (C) 2003 Henrik Brix Andersen <brix@gimp.org> +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +(define (gimp-online-docs-web-site) + (plug-in-web-browser "https://docs.gimp.org/") +) + +(define (gimp-help-main) + (gimp-help "" "gimp-main") +) + +(define (gimp-help-concepts-usage) + (gimp-help "" "gimp-concepts-usage") +) + +(define (gimp-help-using-docks) + (gimp-help "" "gimp-concepts-docks") +) + +(define (gimp-help-using-simpleobjects) + (gimp-help "" "gimp-using-simpleobjects") +) + +(define (gimp-help-using-selections) + (gimp-help "" "gimp-using-selections") +) + +(define (gimp-help-using-fileformats) + (gimp-help "" "gimp-using-fileformats") +) + +(define (gimp-help-using-photography) + (gimp-help "" "gimp-using-photography") +) + +(define (gimp-help-using-web) + (gimp-help "" "gimp-using-web") +) + +(define (gimp-help-concepts-paths) + (gimp-help "" "gimp-concepts-paths") +) + + +; shortcuts to help topics +(script-fu-register "gimp-help-concepts-paths" + _"Using _Paths" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-concepts-paths" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-using-web" + _"_Preparing your Images for the Web" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-using-web" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-using-photography" + _"_Working with Digital Camera Photos" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-using-photography" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-using-fileformats" + _"Create, Open and Save _Files" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-using-fileformats" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-concepts-usage" + _"_Basic Concepts" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-concepts-usage" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-using-docks" + _"How to Use _Dialogs" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-using-docks" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-using-simpleobjects" + _"Drawing _Simple Objects" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-using-simpleobjects" + "<Image>/Help/User Manual") + + +(script-fu-register "gimp-help-using-selections" + _"Create and Use _Selections" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-using-simpleobjects" + "<Image>/Help/User Manual") + +(script-fu-register "gimp-help-main" + _"_[Table of Contents]" + _"Bookmark to the user manual" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-help-main" + "<Image>/Help/User Manual") + + +;; Links to GIMP related web sites + +(define (gimp-online-main-web-site) + (plug-in-web-browser "https://www.gimp.org/") +) + +(define (gimp-online-developer-web-site) + (plug-in-web-browser "https://developer.gimp.org/") +) + +(define (gimp-online-roadmap) + (plug-in-web-browser "https://wiki.gimp.org/wiki/Roadmap") +) + +(define (gimp-online-wiki) + (plug-in-web-browser "https://wiki.gimp.org/wiki/Main_Page") +) + +(define (gimp-online-bugs-features) + (plug-in-web-browser "https://gitlab.gnome.org/GNOME/gimp/issues") +) + +; (define (gimp-online-plug-in-web-site) +; (plug-in-web-browser "https://registry.gimp.org/") +; ) + + +(script-fu-register "gimp-online-main-web-site" + _"_Main Web Site" + _"Bookmark to the GIMP web site" + "Henrik Brix Andersen <brix@gimp.org>" + "Henrik Brix Andersen <brix@gimp.org>" + "2003" + "" +) + +(script-fu-menu-register "gimp-online-main-web-site" + "<Image>/Help/GIMP Online") + + +(script-fu-register "gimp-online-developer-web-site" + _"_Developer Web Site" + _"Bookmark to the GIMP web site" + "Henrik Brix Andersen <brix@gimp.org>" + "Henrik Brix Andersen <brix@gimp.org>" + "2003" + "" +) + +(script-fu-menu-register "gimp-online-developer-web-site" + "<Image>/Help/GIMP Online") + + +(script-fu-register "gimp-online-roadmap" + _"_Roadmap" + _"Bookmark to the roadmap of GIMP" + "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>" + "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>" + "2018" + "" +) + +(script-fu-menu-register "gimp-online-roadmap" + "<Image>/Help/GIMP Online") + + +(script-fu-register "gimp-online-wiki" + _"_Wiki" + _"Bookmark to the wiki of GIMP" + "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>" + "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>" + "2018" + "" +) + +(script-fu-menu-register "gimp-online-wiki" + "<Image>/Help/GIMP Online") + + +(script-fu-register "gimp-online-bugs-features" + _"_Bug Reports and Feature Requests" + _"Bookmark to the bug tracker of GIMP" + "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>" + "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>" + "2018" + "" +) + +(script-fu-menu-register "gimp-online-bugs-features" + "<Image>/Help") + + +(script-fu-register "gimp-online-docs-web-site" + _"_User Manual Web Site" + _"Bookmark to the GIMP web site" + "Roman Joost <romanofski@gimp.org>" + "Roman Joost <romanofski@gimp.org>" + "2006" + "" +) + +(script-fu-menu-register "gimp-online-docs-web-site" + "<Image>/Help/GIMP Online") + + +; (script-fu-register "gimp-online-plug-in-web-site" +; _"Plug-in _Registry" +; _"Bookmark to the GIMP web site" +; "Henrik Brix Andersen <brix@gimp.org>" +; "Henrik Brix Andersen <brix@gimp.org>" +; "2003" +; "" +; ) + +; (script-fu-menu-register "gimp-online-plug-in-web-site" +; "<Image>/Help/GIMP Online") diff --git a/plug-ins/script-fu/scripts/gradient-example.scm b/plug-ins/script-fu/scripts/gradient-example.scm new file mode 100644 index 0000000..3157c88 --- /dev/null +++ b/plug-ins/script-fu/scripts/gradient-example.scm @@ -0,0 +1,81 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Gradient example script --- create an example image of a custom gradient +; Copyright (C) 1997 Federico Mena Quintero +; federico@nuclecu.unam.mx +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +(define (script-fu-gradient-example width + height + gradient-reverse) + (let* ( + (img (car (gimp-image-new width height RGB))) + (drawable (car (gimp-layer-new img width height RGB + "Gradient example" 100 LAYER-MODE-NORMAL))) + + ; Calculate colors for checkerboard... just like in the gradient editor + + (fg-color (* 255 (/ 2 3))) + (bg-color (* 255 (/ 1 3))) + ) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + ; Render background checkerboard + + (gimp-context-push) + + (gimp-context-set-foreground (list fg-color fg-color fg-color)) + (gimp-context-set-background (list bg-color bg-color bg-color)) + (plug-in-checkerboard RUN-NONINTERACTIVE img drawable 0 8) + + (gimp-context-pop) + + ; Render gradient + + (gimp-context-push) + + (gimp-context-set-gradient-reverse gradient-reverse) + (gimp-drawable-edit-gradient-fill drawable + GRADIENT-LINEAR 0 + FALSE 0 0 + TRUE + 0 0 (- width 1) 0) + + (gimp-context-pop) + + ; Terminate + + (gimp-image-undo-enable img) + (gimp-display-new img) + ) +) + +(script-fu-register "script-fu-gradient-example" + _"Custom _Gradient..." + _"Create an image filled with an example of the current gradient" + "Federico Mena Quintero" + "Federico Mena Quintero" + "June 1997" + "" + SF-ADJUSTMENT _"Width" '(400 1 2000 1 10 0 1) + SF-ADJUSTMENT _"Height" '(30 1 2000 1 10 0 1) + SF-TOGGLE _"Gradient reverse" FALSE +) + +(script-fu-menu-register "script-fu-gradient-example" + "<Gradients>") diff --git a/plug-ins/script-fu/scripts/grid-system.scm b/plug-ins/script-fu/scripts/grid-system.scm new file mode 100644 index 0000000..6607a3e --- /dev/null +++ b/plug-ins/script-fu/scripts/grid-system.scm @@ -0,0 +1,95 @@ +;;; grid-system.scm -*-scheme-*- +;;; Time-stamp: <1998/01/20 23:22:02 narazaki@InetQ.or.jp> +;;; This file is a part of: +;;; GIMP (Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis) +;;; Author: Shuji Narazaki (narazaki@InetQ.or.jp) +;;; Version 0.6 + +;;; Code: +(if (not (symbol-bound? 'script-fu-grid-system-x-divides (current-environment))) + (define script-fu-grid-system-x-divides "'(1 g 1)")) +(if (not (symbol-bound? 'script-fu-grid-system-y-divides (current-environment))) + (define script-fu-grid-system-y-divides "'(1 g 1)")) + +(define (script-fu-grid-system img drw x-divides-orig y-divides-orig) + (define (update-segment! s x0 y0 x1 y1) + (aset s 0 x0) + (aset s 1 y0) + (aset s 2 x1) + (aset s 3 y1)) + (define (map proc seq) + (if (null? seq) + '() + (cons (proc (car seq)) + (map proc (cdr seq))))) + (define (convert-g l) + (cond ((null? l) '()) + ((eq? (car l) 'g) (cons 1.618 (convert-g (cdr l)))) + ((eq? (car l) '1/g) (cons 0.618 (convert-g (cdr l)))) + ('else (cons (car l) (convert-g (cdr l)))))) + (define (wrap-list l) + (define (wrap-object obj) + (cond ((number? obj) (string-append (number->string obj) " ")) + ((eq? obj 'g) "g ") + (eq? obj '1/g) "1/g ")) + (string-append "'(" (apply string-append (map wrap-object l)) ")")) + (let* ((drw-width (car (gimp-drawable-width drw))) + (drw-height (car (gimp-drawable-height drw))) + (drw-offset-x (nth 0 (gimp-drawable-offsets drw))) + (drw-offset-y (nth 1 (gimp-drawable-offsets drw))) + (grid-layer #f) + (segment (cons-array 4 'double)) + (stepped-x 0) + (stepped-y 0) + (temp 0) + (total-step-x 0) + (total-step-y 0) + (x-divides (convert-g x-divides-orig)) + (y-divides (convert-g y-divides-orig)) + (total-step-x (apply + x-divides)) + (total-step-y (apply + y-divides))) + + (gimp-image-undo-group-start img) + + (set! grid-layer (car (gimp-layer-copy drw TRUE))) + (gimp-image-insert-layer img grid-layer 0 0) + (gimp-drawable-edit-clear grid-layer) + (gimp-item-set-name grid-layer "Grid Layer") + + (while (not (null? (cdr x-divides))) + (set! stepped-x (+ stepped-x (car x-divides))) + (set! temp (* drw-width (/ stepped-x total-step-x))) + (set! x-divides (cdr x-divides)) + (update-segment! segment + (+ drw-offset-x temp) drw-offset-y + (+ drw-offset-x temp) (+ drw-offset-y drw-height)) + (gimp-pencil grid-layer 4 segment)) + + (while (not (null? (cdr y-divides))) + (set! stepped-y (+ stepped-y (car y-divides))) + (set! temp (* drw-height (/ stepped-y total-step-y))) + (set! y-divides (cdr y-divides)) + (update-segment! segment + drw-offset-x (+ drw-offset-y temp) + (+ drw-offset-x drw-width) (+ drw-offset-y temp)) + (gimp-pencil grid-layer 4 segment)) + + (gimp-image-undo-group-end img) + + (set! script-fu-grid-system-x-divides (wrap-list x-divides-orig)) + (set! script-fu-grid-system-y-divides (wrap-list y-divides-orig)) + (gimp-displays-flush))) + +(script-fu-register "script-fu-grid-system" + _"_Grid..." + _"Draw a grid as specified by the lists of X and Y locations using the current brush" + "Shuji Narazaki <narazaki@InetQ.or.jp>" + "Shuji Narazaki" + "1997" + "RGB*, INDEXED*, GRAY*" + SF-IMAGE "Image to use" 0 + SF-DRAWABLE "Drawable to draw grid" 0 + SF-VALUE _"X divisions" script-fu-grid-system-x-divides + SF-VALUE _"Y divisions" script-fu-grid-system-y-divides +) + diff --git a/plug-ins/script-fu/scripts/guides-from-selection.scm b/plug-ins/script-fu/scripts/guides-from-selection.scm new file mode 100644 index 0000000..b790c86 --- /dev/null +++ b/plug-ins/script-fu/scripts/guides-from-selection.scm @@ -0,0 +1,43 @@ +;; -*-scheme-*- + +(define (script-fu-guides-from-selection image drawable) + (let* ( + (boundaries (gimp-selection-bounds image)) + ;; non-empty INT32 TRUE if there is a selection + (selection (car boundaries)) + (x1 (cadr boundaries)) + (y1 (caddr boundaries)) + (x2 (cadr (cddr boundaries))) + (y2 (caddr (cddr boundaries))) + ) + + ;; need to check for a selection or we get guides right at edges of the image + (if (= selection TRUE) + (begin + (gimp-image-undo-group-start image) + + (gimp-image-add-vguide image x1) + (gimp-image-add-hguide image y1) + (gimp-image-add-vguide image x2) + (gimp-image-add-hguide image y2) + + (gimp-image-undo-group-end image) + (gimp-displays-flush) + ) + ) + ) +) + +(script-fu-register "script-fu-guides-from-selection" + _"New Guides from _Selection" + _"Create four guides around the bounding box of the current selection" + "Alan Horkan" + "Alan Horkan, 2004. Public Domain." + "2004-08-13" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 +) + +(script-fu-menu-register "script-fu-guides-from-selection" + "<Image>/Image/Guides") diff --git a/plug-ins/script-fu/scripts/guides-new-percent.scm b/plug-ins/script-fu/scripts/guides-new-percent.scm new file mode 100644 index 0000000..c42d457 --- /dev/null +++ b/plug-ins/script-fu/scripts/guides-new-percent.scm @@ -0,0 +1,41 @@ +;; -*-scheme-*- + +;; Alan Horkan 2004. No copyright. Public Domain. + +(define (script-fu-guide-new-percent image drawable direction position) + (let* ( + (width (car (gimp-image-width image))) + (height (car (gimp-image-height image))) + ) + + (if (= direction 0) + (set! position (/ (* height position) 100)) + (set! position (/ (* width position) 100)) + ) + + (if (= direction 0) + ;; convert position to pixel + (if (<= position height) (gimp-image-add-hguide image position)) + (if (<= position width) (gimp-image-add-vguide image position)) + ) + + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-guide-new-percent" + _"New Guide (by _Percent)..." + _"Add a guide at the position specified as a percentage of the image size" + "Alan Horkan" + "Alan Horkan, 2004" + "April 2004" + "*" + SF-IMAGE "Input Image" 0 + SF-DRAWABLE "Input Drawable" 0 + SF-OPTION _"_Direction" '(_"Horizontal" + _"Vertical") + SF-ADJUSTMENT _"_Position (in %)" '(50 0 100 1 10 2 1) +) + +(script-fu-menu-register "script-fu-guide-new-percent" + "<Image>/Image/Guides") diff --git a/plug-ins/script-fu/scripts/guides-new.scm b/plug-ins/script-fu/scripts/guides-new.scm new file mode 100644 index 0000000..08217af --- /dev/null +++ b/plug-ins/script-fu/scripts/guides-new.scm @@ -0,0 +1,40 @@ +;; -*-scheme-*- + +;; Alan Horkan 2004. Public Domain. +;; so long as remove this block of comments from your script +;; feel free to use it for whatever you like. + +(define (script-fu-guide-new image + drawable + direction + position) + (let* ( + (width (car (gimp-image-width image))) + (height (car (gimp-image-height image))) + ) + + (if (= direction 0) + ;; check position is inside the image boundaries + (if (<= position height) (gimp-image-add-hguide image position)) + (if (<= position width) (gimp-image-add-vguide image position)) + ) + + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-guide-new" + _"New _Guide..." + _"Add a guide at the orientation and position specified (in pixels)" + "Alan Horkan" + "Alan Horkan, 2004. Public Domain." + "2004-04-02" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-OPTION _"_Direction" '(_"Horizontal" _"Vertical") + SF-ADJUSTMENT _"_Position" (list 0 0 MAX-IMAGE-SIZE 1 10 0 1) +) + +(script-fu-menu-register "script-fu-guide-new" + "<Image>/Image/Guides") diff --git a/plug-ins/script-fu/scripts/guides-remove-all.scm b/plug-ins/script-fu/scripts/guides-remove-all.scm new file mode 100644 index 0000000..61cc3ed --- /dev/null +++ b/plug-ins/script-fu/scripts/guides-remove-all.scm @@ -0,0 +1,30 @@ +;; -*-scheme-*- + +(define (script-fu-guides-remove image drawable) + (let* ((guide-id 0)) + (gimp-image-undo-group-start image) + + (set! guide-id (car (gimp-image-find-next-guide image 0))) + (while (> guide-id 0) + (gimp-image-delete-guide image guide-id) + (set! guide-id (car (gimp-image-find-next-guide image 0))) + ) + + (gimp-image-undo-group-end image) + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-guides-remove" + _"_Remove all Guides" + _"Remove all horizontal and vertical guides" + "Alan Horkan" + "Alan Horkan, 2004. Public Domain." + "April 2004" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 +) + +(script-fu-menu-register "script-fu-guides-remove" + "<Image>/Image/Guides") diff --git a/plug-ins/script-fu/scripts/images/Makefile.am b/plug-ins/script-fu/scripts/images/Makefile.am new file mode 100644 index 0000000..5457226 --- /dev/null +++ b/plug-ins/script-fu/scripts/images/Makefile.am @@ -0,0 +1,12 @@ +## Process this file with automake to produce Makefile.in + +imagesdatadir = $(gimpdatadir)/scripts/images + +imagesdata_DATA = \ + beavis.jpg \ + texture.jpg \ + texture1.jpg \ + texture2.jpg \ + texture3.jpg + +EXTRA_DIST = $(imagesdata_DATA) diff --git a/plug-ins/script-fu/scripts/images/Makefile.in b/plug-ins/script-fu/scripts/images/Makefile.in new file mode 100644 index 0000000..abc16d0 --- /dev/null +++ b/plug-ins/script-fu/scripts/images/Makefile.in @@ -0,0 +1,810 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = plug-ins/script-fu/scripts/images +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(imagesdatadir)" +DATA = $(imagesdata_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +imagesdatadir = $(gimpdatadir)/scripts/images +imagesdata_DATA = \ + beavis.jpg \ + texture.jpg \ + texture1.jpg \ + texture2.jpg \ + texture3.jpg + +EXTRA_DIST = $(imagesdata_DATA) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plug-ins/script-fu/scripts/images/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plug-ins/script-fu/scripts/images/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-imagesdataDATA: $(imagesdata_DATA) + @$(NORMAL_INSTALL) + @list='$(imagesdata_DATA)'; test -n "$(imagesdatadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(imagesdatadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(imagesdatadir)" || exit 1; \ + fi; \ + 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)$(imagesdatadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(imagesdatadir)" || exit $$?; \ + done + +uninstall-imagesdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(imagesdata_DATA)'; test -n "$(imagesdatadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(imagesdatadir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(imagesdatadir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-imagesdataDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-imagesdataDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir 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-imagesdataDATA install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-imagesdataDATA + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/plug-ins/script-fu/scripts/images/beavis.jpg b/plug-ins/script-fu/scripts/images/beavis.jpg Binary files differnew file mode 100644 index 0000000..d555047 --- /dev/null +++ b/plug-ins/script-fu/scripts/images/beavis.jpg diff --git a/plug-ins/script-fu/scripts/images/texture.jpg b/plug-ins/script-fu/scripts/images/texture.jpg Binary files differnew file mode 100644 index 0000000..8890c7f --- /dev/null +++ b/plug-ins/script-fu/scripts/images/texture.jpg diff --git a/plug-ins/script-fu/scripts/images/texture1.jpg b/plug-ins/script-fu/scripts/images/texture1.jpg Binary files differnew file mode 100644 index 0000000..8bb8acd --- /dev/null +++ b/plug-ins/script-fu/scripts/images/texture1.jpg diff --git a/plug-ins/script-fu/scripts/images/texture2.jpg b/plug-ins/script-fu/scripts/images/texture2.jpg Binary files differnew file mode 100644 index 0000000..6b5d2ef --- /dev/null +++ b/plug-ins/script-fu/scripts/images/texture2.jpg diff --git a/plug-ins/script-fu/scripts/images/texture3.jpg b/plug-ins/script-fu/scripts/images/texture3.jpg Binary files differnew file mode 100644 index 0000000..34d0988 --- /dev/null +++ b/plug-ins/script-fu/scripts/images/texture3.jpg diff --git a/plug-ins/script-fu/scripts/lava.scm b/plug-ins/script-fu/scripts/lava.scm new file mode 100644 index 0000000..ae62c7b --- /dev/null +++ b/plug-ins/script-fu/scripts/lava.scm @@ -0,0 +1,135 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Lava effect +; Copyright (c) 1997 Adrian Likins +; aklikins@eos.ncsu.edu +; +; based on a idea by Sven Riedel <lynx@heim8.tu-clausthal.de> +; tweaked a bit by Sven Neumann <neumanns@uni-duesseldorf.de> +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-lava image + drawable + seed + tile_size + mask_size + gradient + keep-selection + separate-layer + current-grad) + (let* ( + (type (car (gimp-drawable-type-with-alpha drawable))) + (image-width (car (gimp-image-width image))) + (image-height (car (gimp-image-height image))) + (active-selection 0) + (selection-bounds 0) + (select-offset-x 0) + (select-offset-y 0) + (select-width 0) + (select-height 0) + (lava-layer 0) + (active-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + (gimp-image-undo-group-start image) + + (if (= (car (gimp-drawable-has-alpha drawable)) FALSE) + (gimp-layer-add-alpha drawable) + ) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + ) + + (set! active-selection (car (gimp-selection-save image))) + (gimp-image-set-active-layer image drawable) + + (set! selection-bounds (gimp-selection-bounds image)) + (set! select-offset-x (cadr selection-bounds)) + (set! select-offset-y (caddr selection-bounds)) + (set! select-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (set! select-height (- (caddr (cddr selection-bounds)) select-offset-y)) + + (if (= separate-layer TRUE) + (begin + (set! lava-layer (car (gimp-layer-new image + select-width + select-height + type + "Lava Layer" + 100 + LAYER-MODE-NORMAL-LEGACY))) + + (gimp-image-insert-layer image lava-layer 0 -1) + (gimp-layer-set-offsets lava-layer select-offset-x select-offset-y) + (gimp-selection-none image) + (gimp-drawable-edit-clear lava-layer) + + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-image-set-active-layer image lava-layer) + ) + ) + + (set! active-layer (car (gimp-image-get-active-layer image))) + + (if (= current-grad FALSE) + (gimp-context-set-gradient gradient) + ) + + (plug-in-solid-noise RUN-NONINTERACTIVE image active-layer FALSE TRUE seed 2 2 2) + (plug-in-cubism RUN-NONINTERACTIVE image active-layer tile_size 2.5 0) + (plug-in-oilify RUN-NONINTERACTIVE image active-layer mask_size 0) + (plug-in-edge RUN-NONINTERACTIVE image active-layer 2 0 0) + (plug-in-gauss-rle RUN-NONINTERACTIVE image active-layer 2 TRUE TRUE) + (plug-in-gradmap RUN-NONINTERACTIVE image active-layer) + + (if (= keep-selection FALSE) + (gimp-selection-none image) + ) + + (gimp-image-set-active-layer image drawable) + (gimp-image-remove-channel image active-selection) + + (gimp-image-undo-group-end image) + (gimp-context-pop) + + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-lava" + _"_Lava..." + _"Fill the current selection with lava" + "Adrian Likins <adrian@gimp.org>" + "Adrian Likins" + "10/12/97" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Seed" '(10 1 30000 1 10 0 1) + SF-ADJUSTMENT _"Size" '(10 0 100 1 10 0 1) + SF-ADJUSTMENT _"Roughness" '(7 3 50 1 10 0 0) + SF-GRADIENT _"Gradient" "German flag smooth" + SF-TOGGLE _"Keep selection" TRUE + SF-TOGGLE _"Separate layer" TRUE + SF-TOGGLE _"Use current gradient" FALSE +) + +(script-fu-menu-register "script-fu-lava" + "<Image>/Filters/Render") diff --git a/plug-ins/script-fu/scripts/line-nova.scm b/plug-ins/script-fu/scripts/line-nova.scm new file mode 100644 index 0000000..8c5c35b --- /dev/null +++ b/plug-ins/script-fu/scripts/line-nova.scm @@ -0,0 +1,123 @@ +;;; line-nova.scm for gimp-1.1 -*-scheme-*- +;;; Time-stamp: <1998/11/25 13:26:44 narazaki@gimp.org> +;;; Author Shuji Narazaki <narazaki@gimp.org> +;;; Version 0.7 + +(define (script-fu-line-nova img drw num-of-lines corn-deg offset variation) + (let* ( + (*points* (cons-array (* 3 2) 'double)) + (modulo fmod) ; in R4RS way + (pi/2 (/ *pi* 2)) + (pi/4 (/ *pi* 4)) + (pi3/4 (* 3 pi/4)) + (pi5/4 (* 5 pi/4)) + (pi3/2 (* 3 pi/2)) + (pi7/4 (* 7 pi/4)) + (2pi (* 2 *pi*)) + (rad/deg (/ 2pi 360)) + (variation/2 (/ variation 2)) + (drw-width (car (gimp-drawable-width drw))) + (drw-height (car (gimp-drawable-height drw))) + (drw-offsets (gimp-drawable-offsets drw)) + (old-selection FALSE) + (radius (max drw-height drw-width)) + (index 0) + (dir-deg/line (/ 360 num-of-lines)) + (fg-color (car (gimp-context-get-foreground))) + ) + (gimp-context-push) + (gimp-context-set-defaults) + (gimp-context-set-foreground fg-color) + + (define (draw-vector beg-x beg-y direction) + + (define (set-point! index x y) + (aset *points* (* 2 index) x) + (aset *points* (+ (* 2 index) 1) y) + ) + (define (deg->rad rad) + (* (modulo rad 360) rad/deg) + ) + (define (set-marginal-point beg-x beg-y direction) + (let ( + (dir1 (deg->rad (+ direction corn-deg))) + (dir2 (deg->rad (- direction corn-deg))) + ) + + (define (aux dir index) + (set-point! index + (+ beg-x (* (cos dir) radius)) + (+ beg-y (* (sin dir) radius))) + ) + + (aux dir1 1) + (aux dir2 2) + ) + ) + + (let ( + (dir0 (deg->rad direction)) + (off (+ offset (- (modulo (rand) variation) variation/2))) + ) + + (set-point! 0 + (+ beg-x (* off (cos dir0))) + (+ beg-y (* off (sin dir0))) + ) + (set-marginal-point beg-x beg-y direction) + (gimp-image-select-polygon img CHANNEL-OP-ADD 6 *points*) + ) + ) + + (gimp-image-undo-group-start img) + + (set! old-selection + (if (eq? (car (gimp-selection-is-empty img)) TRUE) + #f + (car (gimp-selection-save img)) + ) + ) + + (gimp-selection-none img) + (srand (realtime)) + (while (< index num-of-lines) + (draw-vector (+ (nth 0 drw-offsets) (/ drw-width 2)) + (+ (nth 1 drw-offsets) (/ drw-height 2)) + (* index dir-deg/line) + ) + (set! index (+ index 1)) + ) + (gimp-drawable-edit-fill drw FILL-FOREGROUND) + + (if old-selection + (begin + (gimp-image-select-item img CHANNEL-OP-REPLACE old-selection) + ;; (gimp-image-set-active-layer img drw) + ;; delete extra channel by Sven Neumann <neumanns@uni-duesseldorf.de> + (gimp-image-remove-channel img old-selection) + ) + ) + + (gimp-image-undo-group-end img) + (gimp-displays-flush) + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-line-nova" + _"Line _Nova..." + _"Fill a layer with rays emanating outward from its center using the foreground color" + "Shuji Narazaki <narazaki@gimp.org>" + "Shuji Narazaki" + "1997,1998" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Number of lines" '(200 40 1000 1 1 0 1) + SF-ADJUSTMENT _"Sharpness (degrees)" '(1.0 0.0 10.0 0.1 1 1 1) + SF-ADJUSTMENT _"Offset radius" '(100 0 2000 1 1 0 1) + SF-ADJUSTMENT _"Randomness" '(30 1 2000 1 1 0 1) +) + +(script-fu-menu-register "script-fu-line-nova" + "<Image>/Filters/Render") diff --git a/plug-ins/script-fu/scripts/mkbrush.scm b/plug-ins/script-fu/scripts/mkbrush.scm new file mode 100644 index 0000000..be204c4 --- /dev/null +++ b/plug-ins/script-fu/scripts/mkbrush.scm @@ -0,0 +1,272 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Make-Brush - a script for the script-fu program +; by Seth Burgess 1997 <sjburges@ou.edu> +; +; 18-Dec-2000 fixed to work with the new convention (not inverted) of +; gbr saver (jtl@gimp.org) +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-make-brush-rectangular name width height spacing) + (let* ( + (img (car (gimp-image-new width height GRAY))) + (drawable (car (gimp-layer-new img + width height GRAY-IMAGE + "MakeBrush" 100 LAYER-MODE-NORMAL))) + (filename (string-append gimp-directory + "/brushes/r" + (number->string width) + "x" + (number->string height) + ".gbr")) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-fill drawable FILL-BACKGROUND) + + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE 0 0 width height) + + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + + (file-gbr-save 1 img drawable filename filename spacing name) + (gimp-image-delete img) + + (gimp-context-pop) + + (gimp-brushes-refresh) + (gimp-context-set-brush name) + ) +) + +(script-fu-register "script-fu-make-brush-rectangular" + _"_Rectangular..." + _"Create a rectangular brush" + "Seth Burgess <sjburges@ou.edu>" + "Seth Burgess" + "1997" + "" + SF-STRING _"Name" "Rectangle" + SF-ADJUSTMENT _"Width" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Height" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Spacing" '(25 1 100 1 10 1 0) +) + +(script-fu-menu-register "script-fu-make-brush-rectangular" + "<Brushes>") + + +(define (script-fu-make-brush-rectangular-feathered name width height + feathering spacing) + (let* ( + (widthplus (+ width feathering)) + (heightplus (+ height feathering)) + (img (car (gimp-image-new widthplus heightplus GRAY))) + (drawable (car (gimp-layer-new img + widthplus heightplus GRAY-IMAGE + "MakeBrush" 100 LAYER-MODE-NORMAL))) + (filename (string-append gimp-directory + "/brushes/r" + (number->string width) + "x" + (number->string height) + "f" + (number->string feathering) + ".gbr")) + ) + + (gimp-context-push) + (gimp-context-set-paint-mode LAYER-MODE-NORMAL) + (gimp-context-set-opacity 100.0) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-fill drawable FILL-BACKGROUND) + + (cond + ((< 0 feathering) + (gimp-context-set-feather TRUE) + (gimp-context-set-feather-radius feathering feathering) + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE + (/ feathering 2) (/ feathering 2) width height)) + ((>= 0 feathering) + (gimp-context-set-feather FALSE) + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE 0 0 width height)) + ) + + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + + (file-gbr-save 1 img drawable filename filename spacing name) + (gimp-image-delete img) + + (gimp-context-pop) + + (gimp-brushes-refresh) + (gimp-context-set-brush name) + ) +) + +(script-fu-register "script-fu-make-brush-rectangular-feathered" + _"Re_ctangular, Feathered..." + _"Create a rectangular brush with feathered edges" + "Seth Burgess <sjburges@ou.edu>" + "Seth Burgess" + "1997" + "" + SF-STRING _"Name" "Rectangle" + SF-ADJUSTMENT _"Width" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Height" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Feathering" '(4 1 100 1 10 0 1) + SF-ADJUSTMENT _"Spacing" '(25 1 100 1 10 1 0) +) + +(script-fu-menu-register "script-fu-make-brush-rectangular-feathered" + "<Brushes>") + + +(define (script-fu-make-brush-elliptical name width height spacing) + (let* ( + (img (car (gimp-image-new width height GRAY))) + (drawable (car (gimp-layer-new img + width height GRAY-IMAGE + "MakeBrush" 100 LAYER-MODE-NORMAL))) + (filename (string-append gimp-directory + "/brushes/e" + (number->string width) + "x" + (number->string height) + ".gbr")) + ) + + (gimp-context-push) + (gimp-context-set-antialias TRUE) + (gimp-context-set-feather FALSE) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-fill drawable FILL-BACKGROUND) + (gimp-context-set-background '(0 0 0)) + (gimp-image-select-ellipse img CHANNEL-OP-REPLACE 0 0 width height) + + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + + (file-gbr-save 1 img drawable filename filename spacing name) + (gimp-image-delete img) + + (gimp-context-pop) + + (gimp-brushes-refresh) + (gimp-context-set-brush name) + ) +) + +(script-fu-register "script-fu-make-brush-elliptical" + _"_Elliptical..." + _"Create an elliptical brush" + "Seth Burgess <sjburges@ou.edu>" + "Seth Burgess" + "1997" + "" + SF-STRING _"Name" "Ellipse" + SF-ADJUSTMENT _"Width" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Height" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Spacing" '(25 1 100 1 10 1 0) +) + +(script-fu-menu-register "script-fu-make-brush-elliptical" + "<Brushes>") + + +(define (script-fu-make-brush-elliptical-feathered name + width height + feathering spacing) + (let* ( + (widthplus (+ feathering width)) ; add 3 for blurring + (heightplus (+ feathering height)) + (img (car (gimp-image-new widthplus heightplus GRAY))) + (drawable (car (gimp-layer-new img + widthplus heightplus GRAY-IMAGE + "MakeBrush" 100 LAYER-MODE-NORMAL))) + (filename (string-append gimp-directory + "/brushes/e" + (number->string width) + "x" + (number->string height) + "f" + (number->string feathering) + ".gbr")) + ) + + (gimp-context-push) + (gimp-context-set-antialias TRUE) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-fill drawable FILL-BACKGROUND) + + (cond ((> feathering 0) ; keep from taking out gimp with stupid entry. + (gimp-context-set-feather TRUE) + (gimp-context-set-feather-radius feathering feathering) + (gimp-image-select-ellipse img CHANNEL-OP-REPLACE + (/ feathering 2) (/ feathering 2) + width height)) + ((<= feathering 0) + (gimp-context-set-feather FALSE) + (gimp-image-select-ellipse img CHANNEL-OP-REPLACE 0 0 width height))) + + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + + (file-gbr-save 1 img drawable filename filename spacing name) + (gimp-image-delete img) + + (gimp-context-pop) + + (gimp-brushes-refresh) + (gimp-context-set-brush name) + ) +) + +(script-fu-register "script-fu-make-brush-elliptical-feathered" + _"Elli_ptical, Feathered..." + _"Create an elliptical brush with feathered edges" + "Seth Burgess <sjburges@ou.edu>" + "Seth Burgess" + "1997" + "" + SF-STRING _"Name" "Ellipse" + SF-ADJUSTMENT _"Width" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Height" '(20 1 200 1 10 0 1) + SF-ADJUSTMENT _"Feathering" '(4 1 100 1 10 0 1) + SF-ADJUSTMENT _"Spacing" '(25 1 100 1 10 1 0) +) + +(script-fu-menu-register "script-fu-make-brush-elliptical-feathered" + "<Brushes>") diff --git a/plug-ins/script-fu/scripts/old-photo.scm b/plug-ins/script-fu/scripts/old-photo.scm new file mode 100644 index 0000000..110c313 --- /dev/null +++ b/plug-ins/script-fu/scripts/old-photo.scm @@ -0,0 +1,108 @@ +; +; old-photo +; +; +; Chris Gutteridge (cjg@ecs.soton.ac.uk) +; At ECS Dept, University of Southampton, England. + +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; Branko Collin <collin@xs4all.nl> added the possibility to change +; the border size in October 2001. + +; Define the function: + +(define (script-fu-old-photo inImage inLayer inDefocus inBorderSize inSepia inMottle inCopy) + (let ( + (theImage (if (= inCopy TRUE) (car (gimp-image-duplicate inImage)) inImage)) + (theLayer 0) + (theWidth 0) + (theHeight 0) + ) + (if (= inCopy TRUE) + (gimp-image-undo-disable theImage) + (gimp-image-undo-group-start theImage) + ) + + (gimp-selection-all theImage) + + (set! theLayer (car (gimp-image-flatten theImage))) + (if (= inDefocus TRUE) + (plug-in-gauss-rle RUN-NONINTERACTIVE theImage theLayer 1.5 TRUE TRUE) + ) + (if (> inBorderSize 0) + (script-fu-fuzzy-border theImage theLayer '(255 255 255) + inBorderSize TRUE 8 FALSE 100 FALSE TRUE ) + ) + (set! theLayer (car (gimp-image-flatten theImage))) + + (if (= inSepia TRUE) + (begin (gimp-drawable-desaturate theLayer DESATURATE-LIGHTNESS) + (gimp-drawable-brightness-contrast theLayer -0.078125 -0.15625) + (gimp-drawable-color-balance theLayer TRANSFER-SHADOWS TRUE 30 0 -30) + ) + ) + (set! theWidth (car (gimp-image-width theImage))) + (set! theHeight (car (gimp-image-height theImage))) + (if (= inMottle TRUE) + (let ( + (mLayer (car (gimp-layer-new theImage theWidth theHeight + RGBA-IMAGE "Mottle" + 100 LAYER-MODE-DARKEN-ONLY))) + ) + + (gimp-image-insert-layer theImage mLayer 0 0) + (gimp-selection-all theImage) + (gimp-drawable-edit-clear mLayer) + (gimp-selection-none theImage) + (plug-in-noisify RUN-NONINTERACTIVE theImage mLayer TRUE 0 0 0 0.5) + (plug-in-gauss-rle RUN-NONINTERACTIVE theImage mLayer 5 TRUE TRUE) + (set! theLayer (car (gimp-image-flatten theImage))) + ) + ) + (gimp-selection-none theImage) + + (if (= inCopy TRUE) + (begin (gimp-image-clean-all theImage) + (gimp-display-new theImage) + (gimp-image-undo-enable theImage) + ) + (gimp-image-undo-group-end theImage) + ) + + (gimp-displays-flush theImage) + ) +) + +(script-fu-register "script-fu-old-photo" + _"_Old Photo..." + _"Make an image look like an old photo" + "Chris Gutteridge" + "1998, Chris Gutteridge / ECS dept, University of Southampton, England." + "16th April 1998" + "RGB* GRAY*" + SF-IMAGE "The image" 0 + SF-DRAWABLE "The layer" 0 + SF-TOGGLE _"Defocus" TRUE + SF-ADJUSTMENT _"Border size" '(20 0 300 1 10 0 1) + ; since this plug-in uses the fuzzy-border plug-in, I used the + ; values of the latter, with the exception of the initial value + ; and the 'minimum' value. + SF-TOGGLE _"Sepia" TRUE + SF-TOGGLE _"Mottle" FALSE + SF-TOGGLE _"Work on copy" TRUE +) + +(script-fu-menu-register "script-fu-old-photo" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/palette-export.scm b/plug-ins/script-fu/scripts/palette-export.scm new file mode 100644 index 0000000..ecb16df --- /dev/null +++ b/plug-ins/script-fu/scripts/palette-export.scm @@ -0,0 +1,402 @@ +; ----------------------------------------------------------------------------- +; GIMP palette export toolkit - +; Written by Barak Itkin <lightningismyname@gmail.com> +; +; This script includes various exporters for GIMP palettes, and other +; utility function to help in exporting to other (text-based) formats. +; See instruction on adding new exporters at the end +; +; ----------------------------------------------------------------------------- +; Numbers and Math +; ----------------------------------------------------------------------------- + +; For all the operations below, this is the order of respectable digits: +(define conversion-digits (list "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" + "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" + "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" + "w" "x" "y" "z")) + +; Converts a decimal number to another base. The returned number is a string +(define (convert-decimal-to-base num base) + (if (< num base) + (list-ref conversion-digits num) + (let loop ((val num) + (order (inexact->exact (truncate (/ (log num) + (log base))))) + (result "")) + (let* ((power (expt base order)) + (digit (quotient val power))) + (if (zero? order) + (string-append result (list-ref conversion-digits digit)) + (loop (- val (* digit power)) + (pred order) + (string-append result (list-ref conversion-digits digit)))))))) + +; Convert a string representation of a number in some base, to a decimal number +(define (convert-base-to-decimal base num-str) + (define (convert-char num-char) + (if (char-numeric? num-char) + (string->number (string num-char)) + (+ 10 (- (char->integer num-char) (char->integer #\a))) + ) + ) + (define (calc base num-str num) + (if (equal? num-str "") + num + (calc base + (substring num-str 1) + (+ (* num base) (convert-char (string-ref num-str 0))) + ) + ) + ) + (calc base num-str 0) + ) + +; If a string num-str is shorter then size, pad it with pad-str in the +; beginning until it's at least size long +(define (pre-pad-number num-str size pad-str) + (if (< (string-length num-str) size) + (pre-pad-number (string-append pad-str num-str) size pad-str) + num-str + ) + ) + +; ----------------------------------------------------------------------------- +; Color convertors +; ----------------------------------------------------------------------------- + +; The standard way for representing a color would be a list of red +; green and blue (GIMP's default) +(define color-get-red car) +(define color-get-green cadr) +(define color-get-blue caddr) + +; Convert a color to a hexadecimal string +; '(255 255 255) => "#ffffff" + +(define (color-rgb-to-hexa-decimal color) + (string-append "#" + (pre-pad-number + (convert-decimal-to-base (color-get-red color) 16) 2 "0") + (pre-pad-number + (convert-decimal-to-base (color-get-green color) 16) 2 "0") + (pre-pad-number + (convert-decimal-to-base (color-get-blue color) 16) 2 "0") + ) + ) + +; Convert a color to a css color +; '(255 255 255) => "rgb(255, 255, 255)" +(define (color-rgb-to-css color) + (string-append "rgb(" (number->string (color-get-red color)) + ", " (number->string (color-get-green color)) + ", " (number->string (color-get-blue color)) ")") + ) + +; Convert a color to a simple pair of braces with comma separated values +; '(255 255 255) => "(255, 255, 255)" +(define (color-rgb-to-comma-seperated-list color) + (string-append "(" (number->string (color-get-red color)) + ", " (number->string (color-get-green color)) + ", " (number->string (color-get-blue color)) ")") + ) + + +; ----------------------------------------------------------------------------- +; Export utils +; ----------------------------------------------------------------------------- + +; List of characters that should not appear in file names +(define illegal-file-name-chars (list #\\ #\/ #\: #\* #\? #\" #\< #\> #\|)) + +; A function to filter a list lst by a given predicate pred +(define (filter pred lst) + (if (null? lst) + '() + (if (pred (car lst)) + (cons (car lst) (filter pred (cdr lst))) + (filter pred (cdr lst)) + ) + ) + ) + +; A function to check if a certain value obj is inside a list lst +(define (contained? obj lst) (member obj lst)) + +; This functions filters a string to have only characters which are +; either alpha-numeric or contained in more-legal (which is a variable +; holding a list of characters) +(define (clean str more-legal) + (list->string (filter (lambda (ch) (or (char-alphabetic? ch) + (char-numeric? ch) + (contained? ch more-legal))) + (string->list str))) + ) + +; A function that receives the a file-name, and filters out all the +; character that shouldn't appear in file names. Then, it makes sure +; the remaining name isn't only white-spaces. If it's only +; white-spaces, the function returns false. Otherwise, it returns the +; fixed file-name +(define (valid-file-name name) + (let* ((clean (list->string (filter (lambda (ch) + (not (contained? + ch illegal-file-name-chars))) + (string->list name)))) + (clean-without-spaces (list->string (filter (lambda (ch) + (not (char-whitespace? + ch))) + (string->list clean)))) + ) + (if (equal? clean-without-spaces "") + #f + clean + ) + ) + ) + +; Filters a string from all the characters which are not alpha-numeric +; (this also removes whitespaces) +(define (name-alpha-numeric str) + (clean str '()) + ) + +; This function does the same as name-alpha-numeric, with an added +; operation - it removes any numbers from the beginning +(define (name-standard str) + (let ((cleaned (clean str '()))) + (while (char-numeric? (string-ref cleaned 0)) + (set! cleaned (substring cleaned 1)) + ) + cleaned + ) + ) + +(define name-no-conversion (lambda (obj) obj)) +(define color-none (lambda (x) "")) +(define name-none (lambda (x) "")) + +(define displayln (lambda (obj) (display obj) (display "\n"))) + +; The loop for exporting all the colors +(define (export-palette palette-name color-convertor name-convertor + start name-pre name-after name-color-seperator + color-pre color-after entry-seperator end) + + (define (write-color-line index) + (display name-pre) + (display (name-convertor + (car (gimp-palette-entry-get-name palette-name index)))) + (display name-after) + (display name-color-seperator) + (display color-pre) + (display (color-convertor + (car (gimp-palette-entry-get-color palette-name index)))) + (display color-after) + ) + + (let ((color-count (car (gimp-palette-get-colors palette-name))) + (i 0) + ) + + (display start) + + (while (< i (- color-count 1)) + (begin + (write-color-line i) + (display entry-seperator) + (set! i (+ 1 i)) + ) + ) + + (write-color-line i) + (display end) + ) + ) + +(define (register-palette-exporter + export-type export-name file-type description author copyright date) + (script-fu-register (string-append "gimp-palette-export-" export-type) + export-name + description + author + copyright + date + "" + SF-DIRNAME _"Folder for the output file" "" + SF-STRING _"The name of the file to create (if a file with this name already exist, it will be replaced)" + (string-append "palette." file-type) + ) + (script-fu-menu-register (string-append "gimp-palette-export-" export-type) + "<Palettes>/Export as") + ) + +(define (bad-file-name) + (gimp-message (string-append _"The filename you entered is not a suitable name for a file." + "\n\n" + _"All characters in the name are either white-spaces or characters which can not appear in filenames."))) + +; ----------------------------------------------------------------------------- +; Exporters +; ----------------------------------------------------------------------------- + +(define (gimp-palette-export-css directory-name file-name) + (let ((valid-name (valid-file-name file-name))) + (if valid-name + (with-output-to-file (string-append + directory-name DIR-SEPARATOR file-name) + (lambda () (export-palette (car (gimp-context-get-palette)) + color-rgb-to-css + name-alpha-numeric ; name-convertor + "/* Generated with GIMP Palette Export */\n" ; start + "." ; name-pre + "" ; name-after + " { " ; name-color-seperator + "color: " ; color-pre + " }" ; color-after + "\n" ; entry-seperator + "" ; end + ))) + (bad-file-name) + ) + ) + ) +(register-palette-exporter "css" "_CSS stylesheet..." "css" + (string-append _"Export the active palette as a CSS stylesheet with the color entry name as their class name, and the color itself as the color attribute") + "Barak Itkin <lightningismyname@gmail.com>" + "Barak Itkin" "May 15th, 2009") + +(define (gimp-palette-export-php directory-name file-name) + (let ((valid-name (valid-file-name file-name))) + (if valid-name + (with-output-to-file (string-append + directory-name DIR-SEPARATOR file-name) + (lambda () (export-palette (car (gimp-context-get-palette)) + color-rgb-to-hexa-decimal + name-standard ; name-convertor + "<?php\n/* Generated with GIMP Palette Export */\n$colors={\n" ; start + "'" ; name-pre + "'" ; name-after + " => " ; name-color-seperator + "'" ; color-pre + "'" ; color-after + ",\n" ; entry-seperator + "}\n?>" ; end + ))) + (bad-file-name) + ) + ) + ) +(register-palette-exporter "php" "P_HP dictionary..." "php" + _"Export the active palette as a PHP dictionary (name => color)" + "Barak Itkin <lightningismyname@gmail.com>" + "Barak Itkin" "May 15th, 2009") + +(define (gimp-palette-export-python directory-name file-name) + (let ((valid-name (valid-file-name file-name))) + (if valid-name + (with-output-to-file (string-append + directory-name DIR-SEPARATOR file-name) + (lambda () + (let ((palette-name (car (gimp-context-get-palette)))) + (begin (displayln "# Generated with GIMP Palette Export") + (displayln (string-append + "# Based on the palette " palette-name)) + (export-palette palette-name + color-rgb-to-hexa-decimal + name-standard ; name-convertor + "colors={\n" ; start + "'" ; name-pre + "'" ; name-after + ": " ; name-color-seperator + "'" ; color-pre + "'" ; color-after + ",\n" ; entry-seperator + "}" ; end + )))) + ) + (bad-file-name) + ) + ) + ) +(register-palette-exporter "python" "_Python dictionary" "py" + _"Export the active palette as a Python dictionary (name: color)" + "Barak Itkin <lightningismyname@gmail.com>" + "Barak Itkin" "May 15th, 2009") + +(define (gimp-palette-export-text directory-name file-name) + (let ((valid-name (valid-file-name file-name))) + (if valid-name + (with-output-to-file (string-append + directory-name DIR-SEPARATOR file-name) + (lambda () + (export-palette (car (gimp-context-get-palette)) + color-rgb-to-hexa-decimal + name-none ; name-convertor + "" ; start + "" ; name-pre + "" ; name-after + "" ; name-color-seperator + "" ; color-pre + "" ; color-after + "\n" ; entry-seperator + "" ; end + ) + ) + ) + (bad-file-name) + ) + ) + ) +(register-palette-exporter "text" "_Text file..." "txt" + _"Write all the colors in a palette to a text file, one hexadecimal value per line (no names)" + "Barak Itkin <lightningismyname@gmail.com>" + "Barak Itkin" "May 15th, 2009") + +(define (gimp-palette-export-java directory-name file-name) + (let ((valid-name (valid-file-name file-name))) + (if valid-name + (with-output-to-file (string-append directory-name + DIR-SEPARATOR file-name) + (lambda () + (let ((palette-name (car (gimp-context-get-palette)))) + (begin (displayln "") + (displayln "import java.awt.Color;") + (displayln "import java.util.Hashtable;") + (displayln "") + (displayln "// Generated with GIMP palette Export ") + (displayln (string-append + "// Based on the palette " palette-name)) + (displayln (string-append + "public class " + (name-standard palette-name) " {")) + (displayln "") + (displayln " Hashtable<String, Color> colors;") + (displayln "") + (displayln (string-append + " public " + (name-standard palette-name) "() {")) + (export-palette (car (gimp-context-get-palette)) + color-rgb-to-comma-seperated-list + name-no-conversion + " colors = new Hashtable<String,Color>();\n" ; start + " colors.put(\"" ; name-pre + "\"" ; name-after + ", " ; name-color-seperator + "new Color" ; color-pre + ");" ; color-after + "\n" ; entry-seperator + "\n }" ; end + ) + (display "\n}")))) + ) + (bad-file-name) + ) + ) + ) + +(register-palette-exporter "java" "J_ava map..." "java" + _"Export the active palette as a java.util.Hashtable<String, Color>" + "Barak Itkin <lightningismyname@gmail.com>" + "Barak Itkin" "May 15th, 2009") + diff --git a/plug-ins/script-fu/scripts/paste-as-brush.scm b/plug-ins/script-fu/scripts/paste-as-brush.scm new file mode 100644 index 0000000..062e97d --- /dev/null +++ b/plug-ins/script-fu/scripts/paste-as-brush.scm @@ -0,0 +1,74 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; script-fu-paste-as-brush +; Based on select-to-brush by Copyright (c) 1997 Adrian Likins +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-paste-as-brush name filename spacing) + + (let* ((brush-image (car (gimp-edit-paste-as-new-image))) + (brush-draw 0) + (type 0) + (path 0)) + + (if (= TRUE (car (gimp-image-is-valid brush-image))) + (begin + (set! brush-draw (car (gimp-image-get-active-drawable brush-image))) + (set! type (car (gimp-drawable-type brush-draw))) + (set! path (string-append gimp-directory + "/brushes/" + filename + (number->string brush-image) + ".gbr")) + + (if (= type GRAYA-IMAGE) + (begin + (gimp-context-push) + (gimp-context-set-background '(255 255 255)) + (set! brush-draw (car (gimp-image-flatten brush-image))) + (gimp-context-pop) + ) + ) + + (file-gbr-save RUN-NONINTERACTIVE + brush-image brush-draw path path + spacing name) + + (gimp-image-delete brush-image) + + (gimp-brushes-refresh) + (gimp-context-set-brush name) + ) + (gimp-message _"There is no image data in the clipboard to paste.") + ) + ) +) + +(script-fu-register "script-fu-paste-as-brush" + _"New _Brush..." + _"Paste the clipboard contents into a new brush" + "Michael Natterer <mitch@gimp.org>" + "Michael Natterer" + "2005-09-25" + "" + SF-STRING _"_Brush name" "My Brush" + SF-STRING _"_File name" "mybrush" + SF-ADJUSTMENT _"_Spacing" '(25 0 1000 1 1 1 0) +) + +(script-fu-menu-register "script-fu-paste-as-brush" + "<Image>/Edit/Paste as") diff --git a/plug-ins/script-fu/scripts/paste-as-pattern.scm b/plug-ins/script-fu/scripts/paste-as-pattern.scm new file mode 100644 index 0000000..01381a2 --- /dev/null +++ b/plug-ins/script-fu/scripts/paste-as-pattern.scm @@ -0,0 +1,61 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; script-fu-paste-as-pattern +; Based on select-to-pattern by Cameron Gregory, http://www.flamingtext.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. +; +; 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 <https://www.gnu.org/licenses/>. + + +(define (script-fu-paste-as-pattern name filename) + (let* ((pattern-image (car (gimp-edit-paste-as-new-image))) + (pattern-draw 0) + (path 0)) + + (if (= TRUE (car (gimp-image-is-valid pattern-image))) + (begin + (set! pattern-draw (car (gimp-image-get-active-drawable pattern-image))) + (set! path (string-append gimp-directory + "/patterns/" + filename + (number->string pattern-image) + ".pat")) + + (file-pat-save RUN-NONINTERACTIVE + pattern-image pattern-draw path path + name) + + (gimp-image-delete pattern-image) + + (gimp-patterns-refresh) + (gimp-context-set-pattern name) + ) + (gimp-message _"There is no image data in the clipboard to paste.") + ) + ) +) + +(script-fu-register "script-fu-paste-as-pattern" + _"New _Pattern..." + _"Paste the clipboard contents into a new pattern" + "Michael Natterer <mitch@gimp.org>" + "Michael Natterer" + "2005-09-25" + "" + SF-STRING _"_Pattern name" "My Pattern" + SF-STRING _"_File name" "mypattern" +) + +(script-fu-menu-register "script-fu-paste-as-pattern" + "<Image>/Edit/Paste as") diff --git a/plug-ins/script-fu/scripts/perspective-shadow.scm b/plug-ins/script-fu/scripts/perspective-shadow.scm new file mode 100644 index 0000000..1eb40e3 --- /dev/null +++ b/plug-ins/script-fu/scripts/perspective-shadow.scm @@ -0,0 +1,217 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; perspective-shadow.scm version 1.2 2000/11/08 +; +; Copyright (C) 1997-2000 Sven Neumann <sven@gimp.org> +; +; +; Adds a perspective shadow of the current selection or alpha-channel +; as a layer below the active layer +; + +(define (script-fu-perspective-shadow image + drawable + alpha + rel-distance + rel-length + shadow-blur + shadow-color + shadow-opacity + interpolation + allow-resize) + (let* ( + (shadow-blur (max shadow-blur 0)) + (shadow-opacity (min shadow-opacity 100)) + (shadow-opacity (max shadow-opacity 0)) + (rel-length (abs rel-length)) + (alpha (* (/ alpha 180) *pi*)) + (type (car (gimp-drawable-type-with-alpha drawable))) + (image-width (car (gimp-image-width image))) + (image-height (car (gimp-image-height image))) + (from-selection 0) + (active-selection 0) + (shadow-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (if (> rel-distance 24) (set! rel-distance 999999)) + (if (= rel-distance rel-length) (set! rel-distance (+ rel-distance 0.01))) + + (gimp-image-undo-group-start image) + + (gimp-layer-add-alpha drawable) + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! from-selection FALSE)) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))))) + + (let* ((selection-bounds (gimp-selection-bounds image)) + (select-offset-x (cadr selection-bounds)) + (select-offset-y (caddr selection-bounds)) + (select-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (select-height (- (caddr (cddr selection-bounds)) select-offset-y)) + + (abs-length (* rel-length select-height)) + (abs-distance (* rel-distance select-height)) + (half-bottom-width (/ select-width 2)) + (half-top-width (* half-bottom-width + (/ (- rel-distance rel-length) rel-distance))) + + (x0 (+ select-offset-x (+ (- half-bottom-width half-top-width) + (* (cos alpha) abs-length)))) + (y0 (+ select-offset-y (- select-height + (* (sin alpha) abs-length)))) + (x1 (+ x0 (* 2 half-top-width))) + (y1 y0) + (x2 select-offset-x) + (y2 (+ select-offset-y select-height)) + (x3 (+ x2 select-width)) + (y3 y2) + + (shadow-width (+ (- (max x1 x3) (min x0 x2)) (* 2 shadow-blur))) + (shadow-height (+ (- (max y1 y3) (min y0 y2)) (* 2 shadow-blur))) + (shadow-offset-x (- (min x0 x2) shadow-blur)) + (shadow-offset-y (- (min y0 y2) shadow-blur))) + + + (set! shadow-layer (car (gimp-layer-new image + select-width + select-height + type + "Perspective Shadow" + shadow-opacity + LAYER-MODE-NORMAL))) + + + (gimp-image-insert-layer image shadow-layer 0 -1) + (gimp-layer-set-offsets shadow-layer select-offset-x select-offset-y) + (gimp-drawable-fill shadow-layer FILL-TRANSPARENT) + (gimp-context-set-background shadow-color) + (gimp-drawable-edit-fill shadow-layer FILL-BACKGROUND) + (gimp-selection-none image) + + (if (= allow-resize TRUE) + (let* ((new-image-width image-width) + (new-image-height image-height) + (image-offset-x 0) + (image-offset-y 0)) + + (if (< shadow-offset-x 0) + (begin + (set! image-offset-x (abs shadow-offset-x)) + (set! new-image-width (+ new-image-width image-offset-x)) + ; adjust to new coordinate system + (set! x0 (+ x0 image-offset-x)) + (set! x1 (+ x1 image-offset-x)) + (set! x2 (+ x2 image-offset-x)) + (set! x3 (+ x3 image-offset-x)) + )) + + (if (< shadow-offset-y 0) + (begin + (set! image-offset-y (abs shadow-offset-y)) + (set! new-image-height (+ new-image-height image-offset-y)) + ; adjust to new coordinate system + (set! y0 (+ y0 image-offset-y)) + (set! y1 (+ y1 image-offset-y)) + (set! y2 (+ y2 image-offset-y)) + (set! y3 (+ y3 image-offset-y)) + )) + + (if (> (+ shadow-width shadow-offset-x) new-image-width) + (set! new-image-width (+ shadow-width shadow-offset-x))) + + (if (> (+ shadow-height shadow-offset-y) new-image-height) + (set! new-image-height (+ shadow-height shadow-offset-y))) + (gimp-image-resize image + new-image-width + new-image-height + image-offset-x + image-offset-y))) + + (gimp-context-set-transform-direction TRANSFORM-FORWARD) + (gimp-context-set-interpolation interpolation) + (gimp-context-set-transform-recursion 3) + (gimp-context-set-transform-resize TRANSFORM-RESIZE-ADJUST) + + (gimp-item-transform-perspective shadow-layer + x0 y0 + x1 y1 + x2 y2 + x3 y3) + + (if (>= shadow-blur 1.0) + (begin + (gimp-layer-set-lock-alpha shadow-layer FALSE) + (gimp-layer-resize shadow-layer + shadow-width + shadow-height + shadow-blur + shadow-blur) + (plug-in-gauss-rle RUN-NONINTERACTIVE + image + shadow-layer + shadow-blur + TRUE + TRUE)))) + + (if (= from-selection TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-drawable-edit-clear shadow-layer) + (gimp-image-remove-channel image active-selection))) + + (if (and + (= (car (gimp-layer-is-floating-sel drawable)) 0) + (= from-selection FALSE)) + (gimp-image-raise-item image drawable)) + + (gimp-image-set-active-layer image drawable) + (gimp-image-undo-group-end image) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-perspective-shadow" + _"_Perspective..." + _"Add a perspective shadow to the selected region (or alpha)" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "2000/11/08" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Angle" '(45 0 180 1 10 1 0) + SF-ADJUSTMENT _"Relative distance of horizon" '(5 0.1 24.1 0.1 1 1 1) + SF-ADJUSTMENT _"Relative length of shadow" '(1 0.1 24 0.1 1 1 1) + SF-ADJUSTMENT _"Blur radius" '(3 0 1024 1 10 0 0) + SF-COLOR _"Color" '(0 0 0) + SF-ADJUSTMENT _"Opacity" '(80 0 100 1 10 0 0) + SF-ENUM _"Interpolation" '("InterpolationType" "linear") + SF-TOGGLE _"Allow resizing" FALSE +) + +(script-fu-menu-register "script-fu-perspective-shadow" + "<Image>/Filters/Light and Shadow/Shadow") diff --git a/plug-ins/script-fu/scripts/plug-in-compat.init b/plug-ins/script-fu/scripts/plug-in-compat.init new file mode 100644 index 0000000..dd68c2c --- /dev/null +++ b/plug-ins/script-fu/scripts/plug-in-compat.init @@ -0,0 +1,24 @@ +; The Scheme code in this file provides some compatibility with +; scripts that were originally written for use with older versions of +; GIMP. +; +; It provides PDB procedures that used to be provided by plug-ins that +; were since then removed from the GIMP distribution. You should not +; use these in newly written scripts as the functions defined here may +; be removed at some later date. + + +(define (plug-in-color-map run-mode img layer + src-color-1 src-color-2 dest-color-1 dest-color-2 + map-mode) + (gimp-levels layer HISTOGRAM-RED + (car src-color-1) (car src-color-2) 1.0 + (- 255 (car dest-color-1)) (- 255 (car dest-color-2))) + (gimp-levels layer HISTOGRAM-GREEN + (cadr src-color-1) (cadr src-color-2) 1.0 + (- 255 (cadr dest-color-1)) (- 255 (cadr dest-color-2))) + (gimp-levels layer HISTOGRAM-BLUE + (caddr src-color-1) (caddr src-color-2) 1.0 + (- 255 (caddr dest-color-1)) (- 255 (caddr dest-color-2))) + (gimp-levels layer HISTOGRAM-VALUE 0 255 1.0 255 0) +) diff --git a/plug-ins/script-fu/scripts/predator.scm b/plug-ins/script-fu/scripts/predator.scm new file mode 100644 index 0000000..cd1ab14 --- /dev/null +++ b/plug-ins/script-fu/scripts/predator.scm @@ -0,0 +1,137 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Predator effect +; Copyright (c) 1997 Adrian Likins +; aklikins@eos.ncsu.ed +; +; The idea here is too make the image/selection look sort of like +; the view the predator had in the movies. ie, kind of a thermogram +; type of thing. Works best on colorful rgb images. +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-predator image + drawable + edge-amount + pixelize + pixel-size + keep-selection + separate-layer) + (let* ( + (type (car (gimp-drawable-type-with-alpha drawable))) + (image-width (car (gimp-image-width image))) + (image-height (car (gimp-image-height image))) + (active-selection 0) + (from-selection 0) + (selection-bounds 0) + (select-offset-x 0) + (select-offset-y 0) + (select-width 0) + (select-height 0) + (effect-layer 0) + (active-layer 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + (gimp-image-undo-group-start image) + (gimp-layer-add-alpha drawable) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! active-selection (car (gimp-selection-save image))) + (set! from-selection FALSE) + ) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))) + ) + ) + + (set! selection-bounds (gimp-selection-bounds image)) + (set! select-offset-x (cadr selection-bounds)) + (set! select-offset-y (caddr selection-bounds)) + (set! select-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (set! select-height (- (caddr (cddr selection-bounds)) select-offset-y)) + + (if (= separate-layer TRUE) + (begin + (set! effect-layer (car (gimp-layer-new image + select-width + select-height + type + "glow layer" + 100 + LAYER-MODE-NORMAL)) + ) + + (gimp-layer-set-offsets effect-layer select-offset-x select-offset-y) + (gimp-image-insert-layer image effect-layer 0 -1) + (gimp-selection-none image) + (gimp-drawable-edit-clear effect-layer) + + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-edit-copy drawable) + (let ((floating-sel (car (gimp-edit-paste effect-layer FALSE)))) + (gimp-floating-sel-anchor floating-sel) + ) + (gimp-image-set-active-layer image effect-layer) + ) + (set! effect-layer drawable) + ) + (set! active-layer effect-layer) + + ; all the fun stuff goes here + (if (= pixelize TRUE) + (plug-in-pixelize RUN-NONINTERACTIVE image active-layer pixel-size) + ) + (plug-in-max-rgb RUN-NONINTERACTIVE image active-layer 0) + (plug-in-edge RUN-NONINTERACTIVE image active-layer edge-amount 1 0) + + ; clean up the selection copy + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + + (if (= keep-selection FALSE) + (gimp-selection-none image) + ) + + (gimp-image-set-active-layer image drawable) + (gimp-image-remove-channel image active-selection) + (gimp-image-undo-group-end image) + (gimp-displays-flush) + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-predator" + _"_Predator..." + _"Add a 'Predator' effect to the selected region (or alpha)" + "Adrian Likins <adrian@gimp.org>" + "Adrian Likins" + "10/12/97" + "RGB*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Edge amount" '(2 0 24 1 1 0 0) + SF-TOGGLE _"Pixelize" TRUE + SF-ADJUSTMENT _"Pixel amount" '(3 1 16 1 1 0 0) + SF-TOGGLE _"Keep selection" TRUE + SF-TOGGLE _"Separate layer" TRUE +) + +(script-fu-menu-register "script-fu-predator" + "<Image>/Filters/Artistic") diff --git a/plug-ins/script-fu/scripts/reverse-layers.scm b/plug-ins/script-fu/scripts/reverse-layers.scm new file mode 100644 index 0000000..d7e2882 --- /dev/null +++ b/plug-ins/script-fu/scripts/reverse-layers.scm @@ -0,0 +1,53 @@ +; reverse-layers.scm: Reverse the order of layers in the current image. +; Copyright (C) 2006 by Akkana Peck. +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +(define (script-fu-reverse-layers img drawable) + (let* ( + (layers (gimp-image-get-layers img)) + (num-layers (car layers)) + (layer-array (cadr layers)) + (i (- num-layers 1)) + ) + + (gimp-image-undo-group-start img) + + (while (>= i 0) + (let ((layer (aref layer-array i))) + (if (= (car (gimp-layer-is-floating-sel layer)) FALSE) + (gimp-image-lower-item-to-bottom img layer)) + ) + + (set! i (- i 1)) + ) + + (gimp-image-undo-group-end img) + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-reverse-layers" + _"Reverse Layer _Order" + _"Reverse the order of layers in the image" + "Akkana Peck" + "Akkana Peck" + "August 2006" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 +) + +(script-fu-menu-register "script-fu-reverse-layers" + "<Image>/Layer/Stack") diff --git a/plug-ins/script-fu/scripts/ripply-anim.scm b/plug-ins/script-fu/scripts/ripply-anim.scm new file mode 100644 index 0000000..25a2462 --- /dev/null +++ b/plug-ins/script-fu/scripts/ripply-anim.scm @@ -0,0 +1,83 @@ +; "Rippling Image" animation generator (ripply-anim.scm) +; Adam D. Moss (adam@foxbox.org) +; 97/05/18 +; Revised by Saul Goode April 2015. +; +; Designed to be used in conjunction with a plugin capable +; of saving animations (i.e. the GIF plugin). +; + +(define (script-fu-ripply-anim image drawable displacement num-frames edge-type) + (let* ((width (car (gimp-drawable-width drawable))) + (height (car (gimp-drawable-height drawable))) + (work-image (car (gimp-image-new width + height + (quotient (car (gimp-drawable-type drawable)) + 2)))) + (map-layer (car (gimp-layer-new work-image + width + height + (car (gimp-drawable-type drawable)) + "Ripple Map" + 100 + LAYER-MODE-NORMAL)))) + (gimp-context-push) + (gimp-context-set-paint-mode LAYER-MODE-NORMAL) + (gimp-context-set-opacity 100.0) + (gimp-image-undo-disable work-image) + + ; Create a tile-able displacement map in the first layer + (gimp-context-set-background '(127 127 127)) + (gimp-image-insert-layer work-image map-layer 0 0) + (gimp-drawable-edit-fill map-layer FILL-BACKGROUND) + (plug-in-noisify RUN-NONINTERACTIVE work-image map-layer FALSE 1.0 1.0 1.0 0.0) + (plug-in-tile RUN-NONINTERACTIVE work-image map-layer (* width 3) (* height 3) FALSE) + (plug-in-gauss-iir RUN-NONINTERACTIVE work-image map-layer 35 TRUE TRUE) + (gimp-drawable-equalize map-layer TRUE) + (plug-in-gauss-rle RUN-NONINTERACTIVE work-image map-layer 5 TRUE TRUE) + (gimp-drawable-equalize map-layer TRUE) + (gimp-image-crop work-image width height width height) + + ; Create the frame layers + (let loop ((remaining-frames num-frames)) + (unless (zero? remaining-frames) + (let ((frame-layer (car (gimp-layer-new-from-drawable drawable work-image)))) + (gimp-image-insert-layer work-image frame-layer 0 0) + (gimp-item-set-name frame-layer + (string-append "Frame " + (number->string (+ 1 (- num-frames + remaining-frames))) + " (replace)")) + (plug-in-displace RUN-NONINTERACTIVE work-image frame-layer + displacement displacement + TRUE TRUE map-layer map-layer (+ edge-type 1)) + (gimp-item-set-visible frame-layer TRUE)) + (gimp-drawable-offset map-layer + TRUE + OFFSET-BACKGROUND + (/ width num-frames) + (/ height num-frames)) + (loop (- remaining-frames 1)))) + + (gimp-image-remove-layer work-image map-layer) + (gimp-image-undo-enable work-image) + (gimp-display-new work-image) + + (gimp-context-pop))) + +(script-fu-register "script-fu-ripply-anim" + _"_Rippling..." + _"Create a multi-layer image by adding a ripple effect to the current layer" + "Adam D. Moss (adam@foxbox.org), Saul Goode" + "Adam D. Moss, Saul Goode" + "1997, 2015" + "RGB* GRAY*" + SF-IMAGE "Image to animage" 0 + SF-DRAWABLE "Drawable to animate" 0 + SF-ADJUSTMENT _"Rippling strength" '(3 0 256 1 10 1 0) + SF-ADJUSTMENT _"Number of frames" '(15 0 256 1 10 0 1) + SF-OPTION _"Edge behavior" '(_"Wrap" _"Smear" _"Black") + ) + +(script-fu-menu-register "script-fu-ripply-anim" + "<Image>/Filters/Animation/Animators") diff --git a/plug-ins/script-fu/scripts/round-corners.scm b/plug-ins/script-fu/scripts/round-corners.scm new file mode 100644 index 0000000..53711d5 --- /dev/null +++ b/plug-ins/script-fu/scripts/round-corners.scm @@ -0,0 +1,149 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; round-corners.scm version 1.02 1999/12/21 +; +; CHANGE-LOG: +; 1.00 - initial release +; 1.01 - some code cleanup, no real changes +; +; Copyright (C) 1997-1999 Sven Neumann <sven@gimp.org> +; +; +; Rounds the corners of an image, optionally adding a drop-shadow and +; a background layer +; +; The script works on RGB and grayscale images that contain only +; one layer. It creates a copy of the image or can optionally work +; on the original. The script uses the current background color to +; create a background layer. It makes a call to the script drop-shadow. +; +; This script is derived from my script add-shadow, which has become +; obsolete now. + + + +(define (script-fu-round-corners img + drawable + radius + shadow-toggle + shadow-x + shadow-y + shadow-blur + background-toggle + work-on-copy) + (let* ((shadow-blur (abs shadow-blur)) + (radius (abs radius)) + (diam (* 2 radius)) + (width (car (gimp-image-width img))) + (height (car (gimp-image-height img))) + (image (cond ((= work-on-copy TRUE) + (car (gimp-image-duplicate img))) + ((= work-on-copy FALSE) + img))) + ; active drawable is not necessarily the active layer + (pic-layer (car (gimp-image-get-active-layer image))) + (type (car (gimp-drawable-type-with-alpha pic-layer))) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (if (= work-on-copy TRUE) + (gimp-image-undo-disable image) + (gimp-image-undo-group-start image) + ) + + ; add an alpha channel to the image + (gimp-layer-add-alpha pic-layer) + + ; round the edges + (gimp-selection-none image) + (gimp-image-select-rectangle image CHANNEL-OP-ADD 0 0 radius radius) + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT 0 0 diam diam) + (gimp-image-select-rectangle image CHANNEL-OP-ADD (- width radius) 0 radius radius) + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT (- width diam) 0 diam diam) + (gimp-image-select-rectangle image CHANNEL-OP-ADD 0 (- height radius) radius radius) + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT 0 (- height diam) diam diam) + (gimp-image-select-rectangle image CHANNEL-OP-ADD (- width radius) (- height radius) + radius radius) + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT (- width diam) (- height diam) + diam diam) + (gimp-drawable-edit-clear pic-layer) + (gimp-selection-none image) + + ; optionally add a shadow + (if (= shadow-toggle TRUE) + (begin + (script-fu-drop-shadow image + pic-layer + shadow-x + shadow-y + shadow-blur + '(0 0 0) + 80 + TRUE) + (set! width (car (gimp-image-width image))) + (set! height (car (gimp-image-height image))))) + + ; optionally add a background + (if (= background-toggle TRUE) + (let* ((bg-layer (car (gimp-layer-new image + width + height + type + "Background" + 100 + LAYER-MODE-NORMAL)))) + (gimp-drawable-fill bg-layer FILL-BACKGROUND) + (gimp-image-insert-layer image bg-layer 0 -1) + (gimp-image-raise-item image pic-layer) + (if (= shadow-toggle TRUE) + (gimp-image-lower-item image bg-layer)))) + +; clean up after the script + (if (= work-on-copy TRUE) + (gimp-image-undo-enable image) + (gimp-image-undo-group-end image) + ) + + (if (= work-on-copy TRUE) + (gimp-display-new image)) + (gimp-context-pop) + (gimp-displays-flush)) +) + +(script-fu-register "script-fu-round-corners" + _"_Round Corners..." + _"Round the corners of an image and optionally add a drop-shadow and background" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "1999/12/21" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Edge radius" '(15 0 4096 1 10 0 1) + SF-TOGGLE _"Add drop-shadow" TRUE + SF-ADJUSTMENT _"Shadow X offset" '(8 -4096 4096 1 10 0 1) + SF-ADJUSTMENT _"Shadow Y offset" '(8 -4096 4096 1 10 0 1) + SF-ADJUSTMENT _"Blur radius" '(15 0 1024 1 10 0 1) + SF-TOGGLE _"Add background" TRUE + SF-TOGGLE _"Work on copy" TRUE +) + +(script-fu-menu-register "script-fu-round-corners" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/script-fu-compat.init b/plug-ins/script-fu/scripts/script-fu-compat.init new file mode 100644 index 0000000..865cf80 --- /dev/null +++ b/plug-ins/script-fu/scripts/script-fu-compat.init @@ -0,0 +1,457 @@ +;The Scheme code in this file provides some compatibility with scripts that +;were originally written for use with the older SIOD based Script-Fu plug-in +;of GIMP. +; +;All items defined in this file except for the random number routines are +;deprecated. Existing scripts should be updated to avoid the use of the +;compatibility functions and define statements which follow the random number +;generator routines. +; +;The items marked as deprecated at the end of this file may be removed +;at some later date. + + +;The random number generator routines below have been slightly reformatted. +;A couple of define blocks which are not needed have been commented out. +;It has also been extended to enable it to generate numbers with exactly 31 +;bits or more. +;The original file was called rand2.scm and can be found in: +;http://www-2.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/scheme/code/math/random/ + +; Minimal Standard Random Number Generator +; Park & Miller, CACM 31(10), Oct 1988, 32 bit integer version. +; better constants, as proposed by Park. +; By Ozan Yigit + +;(define *seed* 1) + +(define (srand seed) + (set! *seed* seed) + *seed* +) + +(define (msrg-rand) + (let ( + (A 48271) + (M 2147483647) + (Q 44488) + (R 3399) + ) + (let* ( + (hi (quotient *seed* Q)) + (lo (modulo *seed* Q)) + (test (- (* A lo) (* R hi))) + ) + (if (> test 0) + (set! *seed* test) + (set! *seed* (+ test M)) + ) + ) + ) + *seed* +) + +; poker test +; seed 1 +; cards 0-9 inclusive (random 10) +; five cards per hand +; 10000 hands +; +; Poker Hand Example Probability Calculated +; 5 of a kind (aaaaa) 0.0001 0 +; 4 of a kind (aaaab) 0.0045 0.0053 +; Full house (aaabb) 0.009 0.0093 +; 3 of a kind (aaabc) 0.072 0.0682 +; two pairs (aabbc) 0.108 0.1104 +; Pair (aabcd) 0.504 0.501 +; Bust (abcde) 0.3024 0.3058 + +(define (random n) + (define (internal-random n) + (let* ( + (n (inexact->exact (truncate n))) + (M 2147483647) + (slop (modulo M (abs n))) + ) + (let loop ((r (msrg-rand))) + (if (>= r slop) + (modulo r n) + (loop (msrg-rand)) + ) + ) + ) + ) + + ; Negative numbers have a bigger range in twos complement platforms + ; (nearly all platforms out there) than positive ones, so we deal with + ; the numbers in negative form. + (if (> n 0) + (+ n (random (- n))) + + (if (>= n -2147483647) + (internal-random n) + + ; 31-or-more-bits number requested - needs multiple extractions + ; because we don't generate enough random bits. + (if (>= n -1152921504606846975) + ; Up to 2^60-1, two extractions are enough + (let ((q (- (quotient (+ n 1) 1073741824) 1))) ; q=floor(n/2^30) + (let loop () + (let ((big (+ (* (internal-random q) 1073741824) + (internal-random -1073741824) + ) + )) + (if (> big n) + big + (loop) + ) + ) + ) + ) + + ; From 2^60 up, we do three extractions. + ; The code is better understood if seen as generating three + ; digits in base 2^30. q is the maximum value the first digit + ; can take. The other digits can take the full range. + ; + ; The strategy is to generate a random number digit by digit. + ; Here's an example in base 10. Say the input n is 348 + ; (thus requesting a number between 0 and 347). Then the algorithm + ; first calls (internal-random 4) to get a digit between 0 and 3, + ; then (internal-random 10) twice to get two more digits between + ; 0 and 9. Say the result is 366: since it is greater than 347, + ; it's discarded and the process restarted. When the result is + ; <= 347, that's the returned value. The probability of it being + ; greater than the max is always strictly less than 1/2. + ; + ; This is the same idea but in base 2^30 (1073741824). The + ; first digit's weight is (2^30)^2 = 1152921504606846976, + ; similarly to how in our base 10 example, the first digit's + ; weight is 10^2 = 100. In the base 10 example we first divide + ; the target number 348 by 100, taking the ceiling, to get 4. + ; Here we divide by (2^30)^2 instead, taking the ceiling too. + ; + ; The math is a bit obscured by the fact that we generate + ; the digits as negative, so that the result is negative as + ; well, but it's really the same thing. Changing the sign of + ; every digit just changes the sign of the result. + ; + ; This method works for n up to (2^30)^2*(2^31-1) which is + ; 2475880077417839045191401472 (slightly under 91 bits). That + ; covers the 64-bit range comfortably, and some more. If larger + ; numbers are needed, they'll have to be composed with a + ; user-defined procedure. + + (if (>= n -2475880077417839045191401472) + (let ((q (- (quotient (+ n 1) 1152921504606846976) 1))) ; q=floor(n/2^60) + (let loop () + (let ((big (+ (* (internal-random q) 1152921504606846976) + (* (internal-random -1073741824) 1073741824) + (internal-random -1073741824) + ) + )) + (if (> big n) + big + (loop) + ) + ) + ) + ) + (error "requested (random n) range too large") + ) + ) + ) + ) +) + +;(define (rngtest) +; (display "implementation ") +; (srand 1) +; (do +; ( (n 0 (+ n 1)) ) +; ( (>= n 10000) ) +; (msrg-rand) +; ) +; (if (= *seed* 399268537) +; (display "looks correct.") +; (begin +; (display "failed.") +; (newline) +; (display " current seed ") (display *seed*) +; (newline) +; (display " correct seed 399268537") +; ) +; ) +; (newline) +;) + + +;This macro defines a while loop which is needed by some older scripts. +;This is here since it is not defined in R5RS and could be handy to have. + +;This while macro was found at: +;http://www.aracnet.com/~briand/scheme_eval.html +(define-macro (while test . body) + `(let loop () + (cond + (,test + ,@body + (loop) + ) + ) + ) +) + + +;The following define block(s) require the tsx extension to be loaded + +(define (realtime) + (car (gettimeofday)) +) + + +;Items below this line are for compatibility with Script-Fu but +;may be useful enough to keep around + +(define (delq item lis) + (let ((l '())) + (unless (null? lis) + (while (pair? lis) + (if (<> item (car lis)) + (set! l (append l (list (car lis)))) + ) + (set! lis (cdr lis)) + ) + ) + + l + ) +) + +(define (make-list count fill) + (vector->list (make-vector count fill)) +) + +(define (strbreakup str sep) + (let* ( + (seplen (string-length sep)) + (start 0) + (end (string-length str)) + (i start) + (l '()) + ) + + (if (= seplen 0) + (set! l (list str)) + (begin + (while (<= i (- end seplen)) + (if (substring-equal? sep str i (+ i seplen)) + (begin + (if (= start 0) + (set! l (list (substring str start i))) + (set! l (append l (list (substring str start i)))) + ) + (set! start (+ i seplen)) + (set! i (+ i seplen -1)) + ) + ) + + (set! i (+ i 1)) + ) + + (set! l (append l (list (substring str start end)))) + ) + ) + + l + ) +) + +(define (string-downcase str) + (list->string (map char-downcase (string->list str))) +) + +(define (string-trim str) + (string-trim-right (string-trim-left str)) +) + +(define (string-trim-left str) + (let ( + (strlen (string-length str)) + (i 0) + ) + + (while (and (< i strlen) + (char-whitespace? (string-ref str i)) + ) + (set! i (+ i 1)) + ) + + (substring str i (string-length str)) + ) +) + +(define (string-trim-right str) + (let ((i (- (string-length str) 1))) + + (while (and (>= i 0) + (char-whitespace? (string-ref str i)) + ) + (set! i (- i 1)) + ) + + (substring str 0 (+ i 1)) + ) +) + +(define (string-upcase str) + (list->string (map char-upcase (string->list str))) +) + +(define (substring-equal? str str2 start end) + (string=? str (substring str2 start end)) +) + +(define (unbreakupstr stringlist sep) + (let ((str (car stringlist))) + + (set! stringlist (cdr stringlist)) + (while (not (null? stringlist)) + (set! str (string-append str sep (car stringlist))) + (set! stringlist (cdr stringlist)) + ) + + str + ) +) + + +;Items below this line are deprecated and should not be used in new scripts. + +(define aset vector-set!) +(define aref vector-ref) +(define fopen open-input-file) +(define mapcar map) +(define nil '()) +(define nreverse reverse) +(define pow expt) +(define prin1 write) + +(define (print obj . port) + (apply write obj port) + (newline) +) + +(define strcat string-append) +(define string-lessp string<?) +(define symbol-bound? defined?) +(define the-environment current-environment) + +(define *pi* + (* 4 (atan 1.0)) +) + +(define (butlast x) + (if (= (length x) 1) + '() + (reverse (cdr (reverse x))) + ) +) + +(define (cons-array count type) + (case type + ((long) (make-vector count 0)) + ((short) (make-vector count 0)) + ((byte) (make-vector count 0)) + ((double) (make-vector count 0.0)) + ((string) (vector->list (make-vector count ""))) + (else type) + ) +) + +(define (fmod a b) + (- a (* (truncate (/ a b)) b)) +) + +(define (fread arg1 file) + + (define (fread-get-chars count file) + (let ( + (str "") + (c 0) + ) + + (while (> count 0) + (set! count (- count 1)) + (set! c (read-char file)) + (if (eof-object? c) + (set! count 0) + (set! str (string-append str (make-string 1 c))) + ) + ) + + (if (eof-object? c) + () + str + ) + ) + ) + + (if (number? arg1) + (begin + (set! arg1 (inexact->exact (truncate arg1))) + (fread-get-chars arg1 file) + ) + (begin + (set! arg1 (fread-get-chars (string-length arg1) file)) + (string-length arg1) + ) + ) +) + +(define (last x) + (cons (car (reverse x)) '()) +) + +(define (nth k list) + (list-ref list k) +) + +(define (prog1 form1 . form2) + (let ((a form1)) + (if (not (null? form2)) + form2 + ) + a + ) +) + +(define (rand . modulus) + (if (null? modulus) + (msrg-rand) + (apply random modulus) + ) +) + +(define (strcmp str1 str2) + (if (string<? str1 str2) + -1 + (if (string>? str1 str2) + 1 + 0 + ) + ) +) + +(define (trunc n) + (inexact->exact (truncate n)) +) + +(define verbose + (lambda n + (if (or (null? n) (not (number? (car n)))) + 0 + (car n) + ) + ) +) diff --git a/plug-ins/script-fu/scripts/script-fu-set-cmap.scm b/plug-ins/script-fu/scripts/script-fu-set-cmap.scm new file mode 100644 index 0000000..259d5de --- /dev/null +++ b/plug-ins/script-fu/scripts/script-fu-set-cmap.scm @@ -0,0 +1,64 @@ +; Set Colormap v1.1 September 29, 2004 +; by Kevin Cozens <kcozens@interlog.com> +; +; Change the colormap of an image to the colors in a specified palette. +; Included is script-fu-make-cmap-array (available for use in scripts) which +; returns an INT8ARRAY containing the colors from a specified palette. +; This array can be used as the cmap argument for gimp-image-set-colormap. + +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +(define (script-fu-make-cmap-array palette) + (let* ( + (num-colors (car (gimp-palette-get-info palette))) + (cmap (cons-array (* num-colors 3) 'byte)) + (color 0) + (i 0) + ) + + (while (< i num-colors) + (set! color (car (gimp-palette-entry-get-color palette i))) + (aset cmap (* i 3) (car color)) + (aset cmap (+ (* i 3) 1) (cadr color)) + (aset cmap (+ (* i 3) 2) (caddr color)) + (set! i (+ i 1)) + ) + + cmap + ) +) + +(define (script-fu-set-cmap img drawable palette) + (gimp-image-set-colormap img + (* (car (gimp-palette-get-info palette)) 3) + (script-fu-make-cmap-array palette)) + (gimp-displays-flush) +) + +(script-fu-register "script-fu-set-cmap" + _"Se_t Colormap..." + _"Change the colormap of an image to the colors in a specified palette." + "Kevin Cozens <kcozens@interlog.com>" + "Kevin Cozens" + "September 29, 2004" + "INDEXED*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-PALETTE _"Palette" "Default" +) + +(script-fu-menu-register "script-fu-set-cmap" "<Image>/Colors/Map/Colormap") diff --git a/plug-ins/script-fu/scripts/script-fu-util.scm b/plug-ins/script-fu/scripts/script-fu-util.scm new file mode 100644 index 0000000..a22114d --- /dev/null +++ b/plug-ins/script-fu/scripts/script-fu-util.scm @@ -0,0 +1,94 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +; Resizes the image so as to include the selected layer. +; The resulting image has the selected layer size. +; Copyright (C) 2002 Chauk-Mean PROUM +; +(define (script-fu-util-image-resize-from-layer image layer) + (let* ( + (width (car (gimp-drawable-width layer))) + (height (car (gimp-drawable-height layer))) + (posx (- (car (gimp-drawable-offsets layer)))) + (posy (- (cadr (gimp-drawable-offsets layer)))) + ) + + (gimp-image-resize image width height posx posy) + ) +) + +; Add the specified layers to the image. +; The layers will be added in the given order below the +; active layer. +; +(define (script-fu-util-image-add-layers image . layers) + (while (not (null? layers)) + (let ((layer (car layers))) + (set! layers (cdr layers)) + (gimp-image-insert-layer image layer 0 -1) + (gimp-image-lower-item image layer) + ) + ) +) + +; Allow command line usage of GIMP such as: +; +; gimp -i -b '(with-files "*.png" <body>)' +; +; where <body> is the code that handles whatever processing you want to +; perform on the files. There are four variables that are available +; within the <body>: 'basename', 'image', 'filename' and 'layer'. +; The 'basename' is the name of the file with its extension removed, +; while the other three variables are self-explanatory. +; You basically write your code as though it were processing a single +; 'image' and the 'with-files' macro applies it to all of the files +; matching the pattern. +; +; For example, to invert the colors of all of the PNG files in the +; start directory: +; +; gimp -i -b '(with-files "*.png" (gimp-drawable-invert layer FALSE) \ +; (gimp-file-save 1 image layer filename filename ))' +; +; To do the same thing, but saving them as jpeg instead: +; +; gimp -i -b '(with-files "*.png" (gimp-drawable-invert layer FALSE) \ +; (gimp-file-save 1 image layer \ +; (string-append basename ".jpg") \ +; (string-append basename ".jpg") ))' + +(define-macro (with-files pattern . body) + (let ((loop (gensym)) + (filenames (gensym)) + (filename (gensym))) + `(begin + (let ,loop ((,filenames (cadr (file-glob ,pattern 1)))) + (unless (null? ,filenames) + (let* ((filename (car ,filenames)) + (image (catch #f (car (gimp-file-load RUN-NONINTERACTIVE + filename + filename )))) + (layer (if image (car (gimp-image-get-active-layer image)) #f)) + (basename (unbreakupstr (butlast (strbreakup filename ".")) "."))) + (when image + ,@body + (gimp-image-delete image))) + (,loop (cdr ,filenames)) + ) + ) + ) + ) +) diff --git a/plug-ins/script-fu/scripts/script-fu.init b/plug-ins/script-fu/scripts/script-fu.init new file mode 100644 index 0000000..d0c9e30 --- /dev/null +++ b/plug-ins/script-fu/scripts/script-fu.init @@ -0,0 +1,716 @@ +; Initialization file for TinySCHEME 1.40 + +; Per R5RS, up to four deep compositions should be defined +(define (caar x) (car (car x))) +(define (cadr x) (car (cdr x))) +(define (cdar x) (cdr (car x))) +(define (cddr x) (cdr (cdr x))) +(define (caaar x) (car (car (car x)))) +(define (caadr x) (car (car (cdr x)))) +(define (cadar x) (car (cdr (car x)))) +(define (caddr x) (car (cdr (cdr x)))) +(define (cdaar x) (cdr (car (car x)))) +(define (cdadr x) (cdr (car (cdr x)))) +(define (cddar x) (cdr (cdr (car x)))) +(define (cdddr x) (cdr (cdr (cdr x)))) +(define (caaaar x) (car (car (car (car x))))) +(define (caaadr x) (car (car (car (cdr x))))) +(define (caadar x) (car (car (cdr (car x))))) +(define (caaddr x) (car (car (cdr (cdr x))))) +(define (cadaar x) (car (cdr (car (car x))))) +(define (cadadr x) (car (cdr (car (cdr x))))) +(define (caddar x) (car (cdr (cdr (car x))))) +(define (cadddr x) (car (cdr (cdr (cdr x))))) +(define (cdaaar x) (cdr (car (car (car x))))) +(define (cdaadr x) (cdr (car (car (cdr x))))) +(define (cdadar x) (cdr (car (cdr (car x))))) +(define (cdaddr x) (cdr (car (cdr (cdr x))))) +(define (cddaar x) (cdr (cdr (car (car x))))) +(define (cddadr x) (cdr (cdr (car (cdr x))))) +(define (cdddar x) (cdr (cdr (cdr (car x))))) +(define (cddddr x) (cdr (cdr (cdr (cdr x))))) + +;;;; Utility to ease macro creation +(define (macro-expand form) + ((eval (get-closure-code (eval (car form)))) form)) + +(define (macro-expand-all form) + (if (macro? form) + (macro-expand-all (macro-expand form)) + form)) + +(define *compile-hook* macro-expand-all) + + +(macro (unless form) + `(if (not ,(cadr form)) (begin ,@(cddr form)))) + +(macro (when form) + `(if ,(cadr form) (begin ,@(cddr form)))) + +; DEFINE-MACRO Contributed by Andy Gaynor +(macro (define-macro dform) + (if (symbol? (cadr dform)) + `(macro ,@(cdr dform)) + (let ((form (gensym))) + `(macro (,(caadr dform) ,form) + (apply (lambda ,(cdadr dform) ,@(cddr dform)) (cdr ,form)))))) + +; Utilities for math. Notice that inexact->exact is primitive, +; but exact->inexact is not. +(define exact? integer?) +(define (inexact? x) (and (real? x) (not (integer? x)))) +(define (even? n) (= (remainder n 2) 0)) +(define (odd? n) (not (= (remainder n 2) 0))) +(define (zero? n) (= n 0)) +(define (positive? n) (> n 0)) +(define (negative? n) (< n 0)) +(define complex? number?) +(define rational? real?) +(define (abs n) (if (>= n 0) n (- n))) +(define (exact->inexact n) (* n 1.0)) +(define (<> n1 n2) (not (= n1 n2))) + +; min and max must return inexact if any arg is inexact; use (+ n 0.0) +(define (max . lst) + (foldr (lambda (a b) + (if (> a b) + (if (exact? b) a (+ a 0.0)) + (if (exact? a) b (+ b 0.0)))) + (car lst) (cdr lst))) +(define (min . lst) + (foldr (lambda (a b) + (if (< a b) + (if (exact? b) a (+ a 0.0)) + (if (exact? a) b (+ b 0.0)))) + (car lst) (cdr lst))) + +(define (succ x) (+ x 1)) +(define (pred x) (- x 1)) +(define gcd + (lambda a + (if (null? a) + 0 + (let ((aa (abs (car a))) + (bb (abs (cadr a)))) + (if (= bb 0) + aa + (gcd bb (remainder aa bb))))))) +(define lcm + (lambda a + (if (null? a) + 1 + (let ((aa (abs (car a))) + (bb (abs (cadr a)))) + (if (or (= aa 0) (= bb 0)) + 0 + (abs (* (quotient aa (gcd aa bb)) bb))))))) + + +(define (string . charlist) + (list->string charlist)) + +(define (list->string charlist) + (let* ((len (length charlist)) + (newstr (make-string len)) + (fill-string! + (lambda (str i len charlist) + (if (= i len) + str + (begin (string-set! str i (car charlist)) + (fill-string! str (+ i 1) len (cdr charlist))))))) + (fill-string! newstr 0 len charlist))) + +(define (string-fill! s e) + (let ((n (string-length s))) + (let loop ((i 0)) + (if (= i n) + s + (begin (string-set! s i e) (loop (succ i))))))) + +(define (string->list s) + (let loop ((n (pred (string-length s))) (l '())) + (if (= n -1) + l + (loop (pred n) (cons (string-ref s n) l))))) + +(define (string-copy str) + (string-append str)) + +(define (string->anyatom str pred) + (let* ((a (string->atom str))) + (if (pred a) a + (error "string->xxx: not a xxx" a)))) + +(define (string->number str . base) + (let ((n (string->atom str (if (null? base) 10 (car base))))) + (if (number? n) n #f))) + +(define (anyatom->string n pred) + (if (pred n) + (atom->string n) + (error "xxx->string: not a xxx" n))) + + +(define (number->string n . base) + (atom->string n (if (null? base) 10 (car base)))) + +(define (char-cmp? cmp a b) + (cmp (char->integer a) (char->integer b))) +(define (char-ci-cmp? cmp a b) + (cmp (char->integer (char-downcase a)) (char->integer (char-downcase b)))) + +(define (char=? a b) (char-cmp? = a b)) +(define (char<? a b) (char-cmp? < a b)) +(define (char>? a b) (char-cmp? > a b)) +(define (char<=? a b) (char-cmp? <= a b)) +(define (char>=? a b) (char-cmp? >= a b)) + +(define (char-ci=? a b) (char-ci-cmp? = a b)) +(define (char-ci<? a b) (char-ci-cmp? < a b)) +(define (char-ci>? a b) (char-ci-cmp? > a b)) +(define (char-ci<=? a b) (char-ci-cmp? <= a b)) +(define (char-ci>=? a b) (char-ci-cmp? >= a b)) + +; Note the trick of returning (cmp x y) +(define (string-cmp? chcmp cmp a b) + (let ((na (string-length a)) (nb (string-length b))) + (let loop ((i 0)) + (cond + ((= i na) + (if (= i nb) (cmp 0 0) (cmp 0 1))) + ((= i nb) + (cmp 1 0)) + ((chcmp = (string-ref a i) (string-ref b i)) + (loop (succ i))) + (else + (chcmp cmp (string-ref a i) (string-ref b i))))))) + + +(define (string=? a b) (string-cmp? char-cmp? = a b)) +(define (string<? a b) (string-cmp? char-cmp? < a b)) +(define (string>? a b) (string-cmp? char-cmp? > a b)) +(define (string<=? a b) (string-cmp? char-cmp? <= a b)) +(define (string>=? a b) (string-cmp? char-cmp? >= a b)) + +(define (string-ci=? a b) (string-cmp? char-ci-cmp? = a b)) +(define (string-ci<? a b) (string-cmp? char-ci-cmp? < a b)) +(define (string-ci>? a b) (string-cmp? char-ci-cmp? > a b)) +(define (string-ci<=? a b) (string-cmp? char-ci-cmp? <= a b)) +(define (string-ci>=? a b) (string-cmp? char-ci-cmp? >= a b)) + +(define (list . x) x) + +(define (foldr f x lst) + (if (null? lst) + x + (foldr f (f x (car lst)) (cdr lst)))) + +(define (unzip1-with-cdr . lists) + (unzip1-with-cdr-iterative lists '() '())) + +(define (unzip1-with-cdr-iterative lists cars cdrs) + (if (null? lists) + (cons cars cdrs) + (let ((car1 (caar lists)) + (cdr1 (cdar lists))) + (unzip1-with-cdr-iterative + (cdr lists) + (append cars (list car1)) + (append cdrs (list cdr1)))))) + +(define (map proc . lists) + (if (null? lists) + (apply proc) + (if (null? (car lists)) + '() + (let* ((unz (apply unzip1-with-cdr lists)) + (cars (car unz)) + (cdrs (cdr unz))) + (cons (apply proc cars) (apply map (cons proc cdrs))))))) + +(define (for-each proc . lists) + (if (null? lists) + (apply proc) + (if (null? (car lists)) + #t + (let* ((unz (apply unzip1-with-cdr lists)) + (cars (car unz)) + (cdrs (cdr unz))) + (apply proc cars) (apply map (cons proc cdrs)))))) + +(define (list-tail x k) + (if (zero? k) + x + (list-tail (cdr x) (- k 1)))) + +(define (list-ref x k) + (car (list-tail x k))) + +(define (last-pair x) + (if (pair? (cdr x)) + (last-pair (cdr x)) + x)) + +(define (head stream) (car stream)) + +(define (tail stream) (force (cdr stream))) + +(define (vector-equal? x y) + (and (vector? x) (vector? y) (= (vector-length x) (vector-length y)) + (let ((n (vector-length x))) + (let loop ((i 0)) + (if (= i n) + #t + (and (equal? (vector-ref x i) (vector-ref y i)) + (loop (succ i)))))))) + +(define (list->vector x) + (apply vector x)) + +(define (vector-fill! v e) + (let ((n (vector-length v))) + (let loop ((i 0)) + (if (= i n) + v + (begin (vector-set! v i e) (loop (succ i))))))) + +(define (vector->list v) + (let loop ((n (pred (vector-length v))) (l '())) + (if (= n -1) + l + (loop (pred n) (cons (vector-ref v n) l))))) + +;; The following quasiquote macro is due to Eric S. Tiedemann. +;; Copyright 1988 by Eric S. Tiedemann; all rights reserved. +;; +;; Subsequently modified to handle vectors: D. Souflis + +(macro + quasiquote + (lambda (l) + (define (mcons f l r) + (if (and (pair? r) + (eq? (car r) 'quote) + (eq? (car (cdr r)) (cdr f)) + (pair? l) + (eq? (car l) 'quote) + (eq? (car (cdr l)) (car f))) + (if (or (procedure? f) (number? f) (string? f)) + f + (list 'quote f)) + (if (eqv? l vector) + (apply l (eval r)) + (list 'cons l r) + ))) + (define (mappend f l r) + (if (or (null? (cdr f)) + (and (pair? r) + (eq? (car r) 'quote) + (eq? (car (cdr r)) '()))) + l + (list 'append l r))) + (define (foo level form) + (cond ((not (pair? form)) + (if (or (procedure? form) (number? form) (string? form)) + form + (list 'quote form)) + ) + ((eq? 'quasiquote (car form)) + (mcons form ''quasiquote (foo (+ level 1) (cdr form)))) + (#t (if (zero? level) + (cond ((eq? (car form) 'unquote) (car (cdr form))) + ((eq? (car form) 'unquote-splicing) + (error "Unquote-splicing wasn't in a list:" + form)) + ((and (pair? (car form)) + (eq? (car (car form)) 'unquote-splicing)) + (mappend form (car (cdr (car form))) + (foo level (cdr form)))) + (#t (mcons form (foo level (car form)) + (foo level (cdr form))))) + (cond ((eq? (car form) 'unquote) + (mcons form ''unquote (foo (- level 1) + (cdr form)))) + ((eq? (car form) 'unquote-splicing) + (mcons form ''unquote-splicing + (foo (- level 1) (cdr form)))) + (#t (mcons form (foo level (car form)) + (foo level (cdr form))))))))) + (foo 0 (car (cdr l))))) + +;;;;;Helper for the dynamic-wind definition. By Tom Breton (Tehom) +(define (shared-tail x y) + (let ((len-x (length x)) + (len-y (length y))) + (define (shared-tail-helper x y) + (if + (eq? x y) + x + (shared-tail-helper (cdr x) (cdr y)))) + + (cond + ((> len-x len-y) + (shared-tail-helper + (list-tail x (- len-x len-y)) + y)) + ((< len-x len-y) + (shared-tail-helper + x + (list-tail y (- len-y len-x)))) + (#t (shared-tail-helper x y))))) + +;;;;;Dynamic-wind by Tom Breton (Tehom) + +;;Guarded because we must only eval this once, because doing so +;;redefines call/cc in terms of old call/cc +(unless (defined? 'dynamic-wind) + (let + ;;These functions are defined in the context of a private list of + ;;pairs of before/after procs. + ( (*active-windings* '()) + ;;We'll define some functions into the larger environment, so + ;;we need to know it. + (outer-env (current-environment))) + + ;;Poor-man's structure operations + (define before-func car) + (define after-func cdr) + (define make-winding cons) + + ;;Manage active windings + (define (activate-winding! new) + ((before-func new)) + (set! *active-windings* (cons new *active-windings*))) + (define (deactivate-top-winding!) + (let ((old-top (car *active-windings*))) + ;;Remove it from the list first so it's not active during its + ;;own exit. + (set! *active-windings* (cdr *active-windings*)) + ((after-func old-top)))) + + (define (set-active-windings! new-ws) + (unless (eq? new-ws *active-windings*) + (let ((shared (shared-tail new-ws *active-windings*))) + + ;;Define the looping functions. + ;;Exit the old list. Do deeper ones last. Don't do + ;;any shared ones. + (define (pop-many) + (unless (eq? *active-windings* shared) + (deactivate-top-winding!) + (pop-many))) + ;;Enter the new list. Do deeper ones first so that the + ;;deeper windings will already be active. Don't do any + ;;shared ones. + (define (push-many new-ws) + (unless (eq? new-ws shared) + (push-many (cdr new-ws)) + (activate-winding! (car new-ws)))) + + ;;Do it. + (pop-many) + (push-many new-ws)))) + + ;;The definitions themselves. + (eval + `(define call-with-current-continuation + ;;It internally uses the built-in call/cc, so capture it. + ,(let ((old-c/cc call-with-current-continuation)) + (lambda (func) + ;;Use old call/cc to get the continuation. + (old-c/cc + (lambda (continuation) + ;;Call func with not the continuation itself + ;;but a procedure that adjusts the active + ;;windings to what they were when we made + ;;this, and only then calls the + ;;continuation. + (func + (let ((current-ws *active-windings*)) + (lambda (x) + (set-active-windings! current-ws) + (continuation x))))))))) + outer-env) + ;;We can't just say "define (dynamic-wind before thunk after)" + ;;because the lambda it's defined to lives in this environment, + ;;not in the global environment. + (eval + `(define dynamic-wind + ,(lambda (before thunk after) + ;;Make a new winding + (activate-winding! (make-winding before after)) + (let ((result (thunk))) + ;;Get rid of the new winding. + (deactivate-top-winding!) + ;;The return value is that of thunk. + result))) + outer-env))) + +(define call/cc call-with-current-continuation) + + +;;;;; atom? and equal? written by a.k + +;;;; atom? +(define (atom? x) + (not (pair? x))) + +;;;; equal? +(define (equal? x y) + (cond + ((pair? x) + (and (pair? y) + (equal? (car x) (car y)) + (equal? (cdr x) (cdr y)))) + ((vector? x) + (and (vector? y) (vector-equal? x y))) + ((string? x) + (and (string? y) (string=? x y))) + (else (eqv? x y)))) + +;;;; (do ((var init inc) ...) (endtest result ...) body ...) +;; +(macro do + (lambda (do-macro) + (apply (lambda (do vars endtest . body) + (let ((do-loop (gensym))) + `(letrec ((,do-loop + (lambda ,(map (lambda (x) + (if (pair? x) (car x) x)) + `,vars) + (if ,(car endtest) + (begin ,@(cdr endtest)) + (begin + ,@body + (,do-loop + ,@(map (lambda (x) + (cond + ((not (pair? x)) x) + ((< (length x) 3) (car x)) + (else (car (cdr (cdr x)))))) + `,vars))))))) + (,do-loop + ,@(map (lambda (x) + (if (and (pair? x) (cdr x)) + (car (cdr x)) + '())) + `,vars))))) + do-macro))) + +;;;; generic-member +(define (generic-member cmp obj lst) + (cond + ((null? lst) #f) + ((cmp obj (car lst)) lst) + (else (generic-member cmp obj (cdr lst))))) + +(define (memq obj lst) + (generic-member eq? obj lst)) +(define (memv obj lst) + (generic-member eqv? obj lst)) +(define (member obj lst) + (generic-member equal? obj lst)) + +;;;; generic-assoc +(define (generic-assoc cmp obj alst) + (cond + ((null? alst) #f) + ((cmp obj (caar alst)) (car alst)) + (else (generic-assoc cmp obj (cdr alst))))) + +(define (assq obj alst) + (generic-assoc eq? obj alst)) +(define (assv obj alst) + (generic-assoc eqv? obj alst)) +(define (assoc obj alst) + (generic-assoc equal? obj alst)) + +(define (acons x y z) (cons (cons x y) z)) + +;;;; Handy for imperative programs +;;;; Used as: (define-with-return (foo x y) .... (return z) ...) +(macro (define-with-return form) + `(define ,(cadr form) + (call/cc (lambda (return) ,@(cddr form))))) + +;;;; Simple exception handling +; +; Exceptions are caught as follows: +; +; (catch (do-something to-recover and-return meaningful-value) +; (if-something goes-wrong) +; (with-these calls)) +; +; "Catch" establishes a scope spanning multiple call-frames +; until another "catch" is encountered. +; +; Exceptions are thrown with: +; +; (throw "message") +; +; If used outside a (catch ...), reverts to (error "message) + +(define *handlers* (list)) + +(define (push-handler proc) + (set! *handlers* (cons proc *handlers*))) + +(define (pop-handler) + (let ((h (car *handlers*))) + (set! *handlers* (cdr *handlers*)) + h)) + +(define (more-handlers?) + (pair? *handlers*)) + +(define (throw . x) + (if (more-handlers?) + (apply (pop-handler)) + (apply error x))) + +(macro (catch form) + (let ((label (gensym))) + `(call/cc (lambda (exit) + (push-handler (lambda () (exit ,(cadr form)))) + (let ((,label (begin ,@(cddr form)))) + (pop-handler) + ,label))))) + +(define *error-hook* throw) + + +;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL + +(macro (make-environment form) + `(apply (lambda () + ,@(cdr form) + (current-environment)))) + +(define-macro (eval-polymorphic x . envl) + (display envl) + (let* ((env (if (null? envl) (current-environment) (eval (car envl)))) + (xval (eval x env))) + (if (closure? xval) + (make-closure (get-closure-code xval) env) + xval))) + +; Redefine this if you install another package infrastructure +; Also redefine 'package' +(define *colon-hook* eval) + +;;;;; I/O + +(define (input-output-port? p) + (and (input-port? p) (output-port? p))) + +(define (close-port p) + (cond + ((input-output-port? p) (close-input-port p) (close-output-port p)) + ((input-port? p) (close-input-port p)) + ((output-port? p) (close-output-port p)) + (else (throw "Not a port" p)))) + +(define (call-with-input-file s p) + (let ((inport (open-input-file s))) + (if (eq? inport #f) + #f + (let ((res (p inport))) + (close-input-port inport) + res)))) + +(define (call-with-output-file s p) + (let ((outport (open-output-file s))) + (if (eq? outport #f) + #f + (let ((res (p outport))) + (close-output-port outport) + res)))) + +(define (with-input-from-file s p) + (let ((inport (open-input-file s))) + (if (eq? inport #f) + #f + (let ((prev-inport (current-input-port))) + (set-input-port inport) + (let ((res (p))) + (close-input-port inport) + (set-input-port prev-inport) + res))))) + +(define (with-output-to-file s p) + (let ((outport (open-output-file s))) + (if (eq? outport #f) + #f + (let ((prev-outport (current-output-port))) + (set-output-port outport) + (let ((res (p))) + (close-output-port outport) + (set-output-port prev-outport) + res))))) + +(define (with-input-output-from-to-files si so p) + (let ((inport (open-input-file si)) + (outport (open-input-file so))) + (if (not (and inport outport)) + (begin + (close-input-port inport) + (close-output-port outport) + #f) + (let ((prev-inport (current-input-port)) + (prev-outport (current-output-port))) + (set-input-port inport) + (set-output-port outport) + (let ((res (p))) + (close-input-port inport) + (close-output-port outport) + (set-input-port prev-inport) + (set-output-port prev-outport) + res))))) + +; Random number generator (maximum cycle) +(define *seed* 1) +(define (random-next) + (let* ((a 16807) (m 2147483647) (q (quotient m a)) (r (modulo m a))) + (set! *seed* + (- (* a (- *seed* + (* (quotient *seed* q) q))) + (* (quotient *seed* q) r))) + (if (< *seed* 0) (set! *seed* (+ *seed* m))) + *seed*)) +;; SRFI-0 +;; COND-EXPAND +;; Implemented as a macro +(define *features* '(srfi-0 tinyscheme)) + +(define-macro (cond-expand . cond-action-list) + (cond-expand-runtime cond-action-list)) + +(define (cond-expand-runtime cond-action-list) + (if (null? cond-action-list) + #t + (if (cond-eval (caar cond-action-list)) + `(begin ,@(cdar cond-action-list)) + (cond-expand-runtime (cdr cond-action-list))))) + +(define (cond-eval-and cond-list) + (foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list)) + +(define (cond-eval-or cond-list) + (foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list)) + +(define (cond-eval condition) + (cond + ((symbol? condition) + (if (member condition *features*) #t #f)) + ((eq? condition #t) #t) + ((eq? condition #f) #f) + (else (case (car condition) + ((and) (cond-eval-and (cdr condition))) + ((or) (cond-eval-or (cdr condition))) + ((not) (if (not (null? (cddr condition))) + (error "cond-expand : 'not' takes 1 argument") + (not (cond-eval (cadr condition))))) + (else (error "cond-expand : unknown operator" (car condition))))))) + +(gc-verbose #f) diff --git a/plug-ins/script-fu/scripts/select-to-brush.scm b/plug-ins/script-fu/scripts/select-to-brush.scm new file mode 100644 index 0000000..79f0bed --- /dev/null +++ b/plug-ins/script-fu/scripts/select-to-brush.scm @@ -0,0 +1,144 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Selection-to-brush +; Copyright (c) 1997 Adrian Likins +; aklikins@eos.ncsu.edu +; +; Takes the current selection, saves it as a brush, and makes it the +; active brush.. +; +; Parts of this script from Sven Neuman's Drop-Shadow and +; Seth Burgess's mkbrush scripts. +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-selection-to-brush image + drawable + name + filename + spacing) + (let* ( + (type (car (gimp-drawable-type-with-alpha drawable))) + (selection-bounds (gimp-selection-bounds image)) + (select-offset-x (cadr selection-bounds)) + (select-offset-y (caddr selection-bounds)) + (selection-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (selection-height (- (caddr (cddr selection-bounds)) select-offset-y)) + (from-selection 0) + (active-selection 0) + (brush-draw-type 0) + (brush-image-type 0) + (brush-image 0) + (brush-draw 0) + (filename2 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable image) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! from-selection FALSE) + ) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))) + ) + ) + + (gimp-edit-copy drawable) + + (set! brush-draw-type + (if (= type GRAYA-IMAGE) + GRAY-IMAGE + RGBA-IMAGE)) + + (set! brush-image-type + (if (= type GRAYA-IMAGE) + GRAY + RGB)) + + (set! brush-image (car (gimp-image-new selection-width + selection-height + brush-image-type))) + + (set! brush-draw + (car (gimp-layer-new brush-image + selection-width + selection-height + brush-draw-type + "Brush" + 100 + LAYER-MODE-NORMAL))) + + (gimp-image-insert-layer brush-image brush-draw 0 0) + + (gimp-selection-none brush-image) + + (if (= type GRAYA-IMAGE) + (begin + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-fill brush-draw FILL-BACKGROUND)) + (gimp-drawable-fill brush-draw FILL-TRANSPARENT) + ) + + (let ((floating-sel (car (gimp-edit-paste brush-draw FALSE)))) + (gimp-floating-sel-anchor floating-sel) + ) + + (set! filename2 (string-append gimp-directory + "/brushes/" + filename + (number->string image) + ".gbr")) + + (file-gbr-save 1 brush-image brush-draw filename2 filename2 spacing name) + + (if (= from-selection TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-image-remove-channel image active-selection) + ) + ) + + (gimp-image-undo-enable image) + (gimp-image-set-active-layer image drawable) + (gimp-image-delete brush-image) + (gimp-displays-flush) + + (gimp-context-pop) + + (gimp-brushes-refresh) + (gimp-context-set-brush name) + ) +) + +(script-fu-register "script-fu-selection-to-brush" + _"To _Brush..." + _"Convert a selection to a brush" + "Adrian Likins <adrian@gimp.org>" + "Adrian Likins" + "10/07/97" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-STRING _"_Brush name" "My Brush" + SF-STRING _"_File name" "mybrush" + SF-ADJUSTMENT _"_Spacing" '(25 0 1000 1 1 1 0) +) diff --git a/plug-ins/script-fu/scripts/select-to-image.scm b/plug-ins/script-fu/scripts/select-to-image.scm new file mode 100644 index 0000000..dec088d --- /dev/null +++ b/plug-ins/script-fu/scripts/select-to-image.scm @@ -0,0 +1,89 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Selection to Image +; Copyright (c) 1997 Adrian Likins +; aklikins@eos.ncsu.edu +; +; Takes the Current selection and saves it as a separate image. +; +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-selection-to-image image drawable) + (let* ( + (draw-type (car (gimp-drawable-type-with-alpha drawable))) + (image-type (car (gimp-image-base-type image))) + (selection-bounds (gimp-selection-bounds image)) + (select-offset-x (cadr selection-bounds)) + (select-offset-y (caddr selection-bounds)) + (selection-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (selection-height (- (caddr (cddr selection-bounds)) select-offset-y)) + (active-selection 0) + (from-selection 0) + (new-image 0) + (new-draw 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable image) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! active-selection (car (gimp-selection-save image))) + (set! from-selection FALSE) + ) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))) + ) + ) + + (gimp-edit-copy drawable) + + (set! new-image (car (gimp-image-new selection-width + selection-height image-type))) + (set! new-draw (car (gimp-layer-new new-image + selection-width selection-height + draw-type "Selection" 100 LAYER-MODE-NORMAL))) + (gimp-image-insert-layer new-image new-draw 0 0) + (gimp-drawable-fill new-draw FILL-BACKGROUND) + + (let ((floating-sel (car (gimp-edit-paste new-draw FALSE)))) + (gimp-floating-sel-anchor floating-sel) + ) + + (gimp-image-undo-enable image) + (gimp-image-set-active-layer image drawable) + (gimp-display-new new-image) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-selection-to-image" + _"To _Image" + _"Convert a selection to an image" + "Adrian Likins <adrian@gimp.org>" + "Adrian Likins" + "10/07/97" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 +) diff --git a/plug-ins/script-fu/scripts/select-to-pattern.scm b/plug-ins/script-fu/scripts/select-to-pattern.scm new file mode 100644 index 0000000..6b2f9eb --- /dev/null +++ b/plug-ins/script-fu/scripts/select-to-pattern.scm @@ -0,0 +1,103 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Based on select-to-brush by +; Copyright (c) 1997 Adrian Likins aklikins@eos.ncsu.edu +; Author Cameron Gregory, http://www.flamingtext.com/ +; +; Takes the current selection, saves it as a pattern and makes it the active +; pattern +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-selection-to-pattern image drawable desc filename) + + (let* ( + (selection-width 0) + (selection-height 0) + (selection-bounds 0) + (select-offset-x 0) + (select-offset-y 0) + (pattern-draw-type 0) + (pattern-image-type 0) + (pattern-image 0) + (pattern-draw 0) + (filename2 0) + ) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (set! selection-width (car (gimp-drawable-width drawable))) + (set! selection-height (car (gimp-drawable-height drawable))) + ) + (begin + (set! selection-bounds (gimp-drawable-mask-bounds drawable)) + (set! select-offset-x (cadr selection-bounds)) + (set! select-offset-y (caddr selection-bounds)) + (set! selection-width (- (cadr (cddr selection-bounds)) select-offset-x)) + (set! selection-height (- (caddr (cddr selection-bounds)) select-offset-y)) + ) + ) + + (if (= (car (gimp-drawable-has-alpha drawable)) TRUE) + (set! pattern-draw-type RGBA-IMAGE) + (set! pattern-draw-type RGB-IMAGE) + ) + + (set! pattern-image-type RGB) + + (set! pattern-image (car (gimp-image-new selection-width selection-height + pattern-image-type))) + + (set! pattern-draw + (car (gimp-layer-new pattern-image selection-width selection-height + pattern-draw-type "Pattern" 100 LAYER-MODE-NORMAL))) + + (gimp-drawable-fill pattern-draw FILL-TRANSPARENT) + + (gimp-image-insert-layer pattern-image pattern-draw 0 0) + + (gimp-edit-copy drawable) + + (let ((floating-sel (car (gimp-edit-paste pattern-draw FALSE)))) + (gimp-floating-sel-anchor floating-sel)) + + (set! filename2 (string-append gimp-directory + "/patterns/" + filename + (number->string image) + ".pat")) + + (file-pat-save 1 pattern-image pattern-draw filename2 "" desc) + (gimp-patterns-refresh) + (gimp-context-set-pattern desc) + + (gimp-image-delete pattern-image) + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-selection-to-pattern" + _"To _Pattern..." + _"Convert a selection to a pattern" + "Cameron Gregory <cameron@bloke.com>" + "Cameron Gregory" + "09/02/2003" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-STRING _"_Pattern name" "My Pattern" + SF-STRING _"_File name" "mypattern" +) diff --git a/plug-ins/script-fu/scripts/selection-round.scm b/plug-ins/script-fu/scripts/selection-round.scm new file mode 100644 index 0000000..afbc91c --- /dev/null +++ b/plug-ins/script-fu/scripts/selection-round.scm @@ -0,0 +1,164 @@ +; selection-rounded-rectangle.scm -*-scheme-*- + +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + +; CHANGE-LOG: +; 1.00 - initial release +; 1.01 - some code cleanup, no real changes +; 1.02 - made script undoable + +; 2.00 - ALAN's Branch. changed name, menu, location, and description +; 2.01 - fixed to work if there was no current selection. +; 2.02 - changed scale to percentages, usability tweaking. +; 2.10 - added concave round edges, updated description. +; 2.11 - tweeked description, changed comments, relinquished any rights. + +; Copyright (C) 1997, 1998, Sven Neumann +; Copyright (C) 2004, Alan Horkan. +; Alan Horkan relinquishes all rights to his changes, +; full ownership of this script belongs to Sven Neumann. + +(define (script-fu-selection-rounded-rectangle image drawable radius concave) + (gimp-image-undo-group-start image) + + (if (= (car (gimp-selection-is-empty image)) TRUE) (gimp-selection-all image)) + (let* ( + (radius (/ radius 100)) ; convert from percentages + (radius (min radius 1.0)) + (radius (max radius 0.0)) + (select-bounds (gimp-selection-bounds image)) + (has-selection (car select-bounds)) + (select-x1 (cadr select-bounds)) + (select-y1 (caddr select-bounds)) + (select-x2 (cadr (cddr select-bounds))) + (select-y2 (caddr (cddr select-bounds))) + (select-width (- select-x2 select-x1)) + (select-height (- select-y2 select-y1)) + (cut-radius 0) + (ellipse-radius 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + ;; select to the full bounds of the selection, + ;; fills in irregular shapes or holes. + (gimp-image-select-rectangle image CHANNEL-OP-ADD + select-x1 select-y1 select-width select-height) + + (if (> select-width select-height) + (set! cut-radius (trunc (+ 1 (* radius (/ select-height 2))))) + (set! cut-radius (trunc (+ 1 (* radius (/ select-width 2))))) + ) + (set! ellipse-radius (* cut-radius 2)) + + (gimp-context-set-antialias TRUE) + ;; cut away rounded (concave) corners + ; top right + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT + (- select-x1 cut-radius) + (- select-y1 cut-radius) + (* cut-radius 2) + (* cut-radius 2)) + ; lower left + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT + (- select-x1 cut-radius) + (- select-y2 cut-radius) + (* cut-radius 2) + (* cut-radius 2)) + ; top right + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT + (- select-x2 cut-radius) + (- select-y1 cut-radius) + (* cut-radius 2) + (* cut-radius 2)) + ; bottom left + (gimp-image-select-ellipse image CHANNEL-OP-SUBTRACT + (- select-x2 cut-radius) + (- select-y2 cut-radius) + (* cut-radius 2) + (* cut-radius 2)) + + ;; add in rounded (convex) corners + (if (= concave FALSE) + (begin + (gimp-image-select-ellipse image + CHANNEL-OP-ADD + select-x1 + select-y1 + ellipse-radius + ellipse-radius) + (gimp-image-select-ellipse image + CHANNEL-OP-ADD + select-x1 + (- select-y2 ellipse-radius) + ellipse-radius + ellipse-radius) + (gimp-image-select-ellipse image + CHANNEL-OP-ADD + (- select-x2 ellipse-radius) + select-y1 + ellipse-radius + ellipse-radius) + (gimp-image-select-ellipse image + CHANNEL-OP-ADD + (- select-x2 ellipse-radius) + (- select-y2 ellipse-radius) + ellipse-radius + ellipse-radius) + ) + ) + + (gimp-image-undo-group-end image) + (gimp-displays-flush) + (gimp-context-pop) + ) +) + + +(define (script-fu-selection-round image drawable radius) + (script-fu-selection-rounded-rectangle image drawable (* radius 100) FALSE) +) + + +(script-fu-register "script-fu-selection-rounded-rectangle" + _"Rounded R_ectangle..." + _"Round the corners of the current selection" + "Alan Horkan, Sven Neumann" ; authors + "Sven Neumann" ; copyright + "2004/06/07" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"R_adius (%)" '(50 0 100 1 10 0 0) + SF-TOGGLE _"Co_ncave" FALSE +) + +(script-fu-register "script-fu-selection-round" + "" + "This procedure is deprecated! Use 'script-fu-selection-rounded-rectangle' instead." + "Sven Neumann" ; authors + "Sven Neumann" ; copyright + "1998/02/06" + "*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT "Relative radius" '(1 0 128 0.1 1 1 1) +) + +(script-fu-menu-register "script-fu-selection-rounded-rectangle" + "<Image>/Select/Modify") diff --git a/plug-ins/script-fu/scripts/slide.scm b/plug-ins/script-fu/scripts/slide.scm new file mode 100644 index 0000000..4889d62 --- /dev/null +++ b/plug-ins/script-fu/scripts/slide.scm @@ -0,0 +1,261 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; slide.scm version 0.41 2004/03/28 +; +; CHANGE-LOG: +; 0.20 - first public release +; 0.30 - some code cleanup +; now uses the rotate plug-in to improve speed +; 0.40 - changes to work with gimp-1.1 +; if the image was rotated, rotate the whole thing back when finished +; 0.41 - changes to work with gimp-2.0, slightly correct text offsets, +; Nils Philippsen <nphilipp@redhat.com> 2004/03/28 +; +; !still in development! +; TODO: - change the script so that the film is rotated, not the image +; - antialiasing +; - make 'add background' an option +; - ? +; +; Copyright (C) 1997-1999 Sven Neumann <sven@gimp.org> +; +; makes your picture look like a slide +; +; The script works on RGB and grayscale images that contain only +; one layer. The image is cropped to fit into an aspect ratio of 1:1,5. +; It creates a copy of the image or can optionally work on the original. +; The script uses the current background color to create a background +; layer. + + +(define (script-fu-slide img + drawable + text + number + fontname + font-color + work-on-copy) + + (define (crop width height ratio) + (if (>= width (* ratio height)) + (* ratio height) + width + ) + ) + + (let* ( + (type (car (gimp-drawable-type-with-alpha drawable))) + (image (cond ((= work-on-copy TRUE) + (car (gimp-image-duplicate img))) + ((= work-on-copy FALSE) + img))) + (owidth (car (gimp-image-width image))) + (oheight (car (gimp-image-height image))) + (ratio (if (>= owidth oheight) (/ 3 2) + (/ 2 3))) + (crop-width (crop owidth oheight ratio)) + (crop-height (/ crop-width ratio)) + (width (* (max crop-width crop-height) 1.05)) + (height (* (min crop-width crop-height) 1.5)) + (hole-width (/ width 20)) + (hole-space (/ width 8)) + (hole-height (/ width 12)) + (hole-radius (/ hole-width 4)) + (hole-start (- (/ (rand 1000) 1000) 0.5)) + (film-layer (car (gimp-layer-new image + width + height + type + "Film" + 100 + LAYER-MODE-NORMAL))) + (bg-layer (car (gimp-layer-new image + width + height + type + "Background" + 100 + LAYER-MODE-NORMAL))) + (pic-layer (car (gimp-image-get-active-drawable image))) + (numbera (string-append number "A")) + ) + + (gimp-context-push) + (gimp-context-set-paint-mode LAYER-MODE-NORMAL) + (gimp-context-set-opacity 100.0) + (gimp-context-set-feather FALSE) + + (if (= work-on-copy TRUE) + (gimp-image-undo-disable image) + (gimp-image-undo-group-start image) + ) + +; add an alpha channel to the image + (gimp-layer-add-alpha pic-layer) + +; crop, resize and eventually rotate the image + (gimp-image-crop image + crop-width + crop-height + (/ (- owidth crop-width) 2) + (/ (- oheight crop-height) 2)) + (gimp-image-resize image + width + height + (/ (- width crop-width) 2) + (/ (- height crop-height) 2)) + (if (< ratio 1) + (plug-in-rotate RUN-NONINTERACTIVE image pic-layer 1 FALSE) + ) + +; add the background layer + (gimp-drawable-fill bg-layer FILL-BACKGROUND) + (gimp-image-insert-layer image bg-layer 0 -1) + +; add the film layer + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-fill film-layer FILL-BACKGROUND) + (gimp-image-insert-layer image film-layer 0 -1) + +; add the text + (gimp-context-set-foreground font-color) + (gimp-floating-sel-anchor (car (gimp-text-fontname image + film-layer + (+ hole-start (* -0.25 width)) + (* 0.01 height) + text + 0 + TRUE + (* 0.040 height) PIXELS fontname))) + (gimp-floating-sel-anchor (car (gimp-text-fontname image + film-layer + (+ hole-start (* 0.75 width)) + (* 0.01 height) + text + 0 + TRUE + (* 0.040 height) PIXELS + fontname ))) + (gimp-floating-sel-anchor (car (gimp-text-fontname image + film-layer + (+ hole-start (* 0.35 width)) + 0.0 + number + 0 + TRUE + (* 0.050 height) PIXELS + fontname ))) + (gimp-floating-sel-anchor (car (gimp-text-fontname image + film-layer + (+ hole-start (* 0.35 width)) + (* 0.94 height) + number + 0 + TRUE + (* 0.050 height) PIXELS + fontname ))) + (gimp-floating-sel-anchor (car (gimp-text-fontname image + film-layer + (+ hole-start (* 0.85 width)) + (* 0.945 height) + numbera + 0 + TRUE + (* 0.045 height) PIXELS + fontname ))) + +; create a mask for the holes and cut them out + (let* ( + (film-mask (car (gimp-layer-create-mask film-layer ADD-MASK-WHITE))) + (hole hole-start) + (top-y (* height 0.06)) + (bottom-y (* height 0.855)) + ) + + (gimp-layer-add-mask film-layer film-mask) + + (gimp-selection-none image) + (while (< hole 8) + (gimp-image-select-rectangle image + CHANNEL-OP-ADD + (* hole-space hole) + top-y + hole-width + hole-height) + (gimp-image-select-rectangle image + CHANNEL-OP-ADD + (* hole-space hole) + bottom-y + hole-width + hole-height) + (set! hole (+ hole 1)) + ) + + (gimp-context-set-foreground '(0 0 0)) + (gimp-drawable-edit-fill film-mask FILL-BACKGROUND) + (gimp-selection-none image) + (plug-in-gauss-rle RUN-NONINTERACTIVE image film-mask hole-radius TRUE TRUE) + (gimp-threshold film-mask 127 255) + + (gimp-layer-remove-mask film-layer MASK-APPLY) + ) + +; reorder the layers + (gimp-image-raise-item image pic-layer) + (gimp-image-raise-item image pic-layer) + +; eventually rotate the whole thing back + (if (< ratio 1) + (plug-in-rotate RUN-NONINTERACTIVE image pic-layer 3 TRUE) + ) + +; clean up after the script + (gimp-selection-none image) + + (if (= work-on-copy TRUE) + (begin + (gimp-display-new image) + (gimp-image-undo-enable image) + ) + (gimp-image-undo-group-end image) + ) + + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-slide" + _"_Slide..." + _"Add a slide-film like frame, sprocket holes, and labels to an image" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "2004/03/28" + "RGB GRAY" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-STRING _"Text" "GIMP" + SF-STRING _"Number" "32" + SF-FONT _"Font" "Serif" + SF-COLOR _"Font color" '(255 180 0) + SF-TOGGLE _"Work on copy" TRUE +) + +(script-fu-menu-register "script-fu-slide" + "<Image>/Filters/Decor") diff --git a/plug-ins/script-fu/scripts/spinning-globe.scm b/plug-ins/script-fu/scripts/spinning-globe.scm new file mode 100644 index 0000000..1549830 --- /dev/null +++ b/plug-ins/script-fu/scripts/spinning-globe.scm @@ -0,0 +1,110 @@ +; +; anim_sphere +; +; +; Chris Gutteridge (cjg@ecs.soton.ac.uk) +; At ECS Dept, University of Southampton, England. +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +; Define the function: + +(define (script-fu-spinning-globe inImage + inLayer + inFrames + inFromLeft + inTransparent + inIndex + inCopy) + (let* ( + (theImage (if (= inCopy TRUE) + (car (gimp-image-duplicate inImage)) + inImage)) + (theLayer (car (gimp-image-get-active-layer theImage))) + (n 0) + (ang (* (/ 360 inFrames) + (if (= inFromLeft TRUE) 1 -1) )) + (theFrame 0) + ) + + (gimp-layer-add-alpha theLayer) + + (while (> inFrames n) + (set! n (+ n 1)) + (set! theFrame (car (gimp-layer-copy theLayer FALSE))) + (gimp-image-insert-layer theImage theFrame 0 0) + (gimp-item-set-name theFrame + (string-append "Anim Frame: " + (number->string (- inFrames n) 10) + " (replace)")) + (plug-in-map-object RUN-NONINTERACTIVE + theImage theFrame ; mapping + 1 ; viewpoint + 0.5 0.5 2.0 ; object pos + 0.5 0.5 0.0 ; first axis + 1.0 0.0 0.0 ; 2nd axis + 0.0 1.0 0.0 ; axis rotation + 0.0 (* n ang) 0.0 ; light (type, color) + 0 '(255 255 255) ; light position + -0.5 -0.5 2.0 ; light direction + -1.0 -1.0 1.0 ; material (amb, diff, refl, spec, high) + 0.3 1.0 0.5 0.0 27.0 ; antialias + TRUE ; tile + FALSE ; new image + FALSE ; transparency + inTransparent ; radius + 0.25 ; unused parameters + 1.0 1.0 1.0 1.0 + -1 -1 -1 -1 -1 -1 -1 -1 + ) + ) + + (gimp-image-remove-layer theImage theLayer) + (plug-in-autocrop RUN-NONINTERACTIVE theImage theFrame) + + (if (= inIndex 0) + () + (gimp-image-convert-indexed theImage CONVERT-DITHER-FS CONVERT-PALETTE-GENERATE inIndex + FALSE FALSE "")) + + (if (= inCopy TRUE) + (begin + (gimp-image-clean-all theImage) + (gimp-display-new theImage) + ) + ) + + (gimp-displays-flush) + ) +) + +(script-fu-register + "script-fu-spinning-globe" + _"_Spinning Globe..." + _"Create an animation by mapping the current image onto a spinning sphere" + "Chris Gutteridge" + "1998, Chris Gutteridge / ECS dept, University of Southampton, England." + "16th April 1998" + "RGB* GRAY*" + SF-IMAGE "The Image" 0 + SF-DRAWABLE "The Layer" 0 + SF-ADJUSTMENT _"Frames" '(10 1 360 1 10 0 1) + SF-TOGGLE _"Turn from left to right" FALSE + SF-TOGGLE _"Transparent background" TRUE + SF-ADJUSTMENT _"Index to n colors (0 = remain RGB)" '(63 0 256 1 10 0 1) + SF-TOGGLE _"Work on copy" TRUE +) + +(script-fu-menu-register "script-fu-spinning-globe" + "<Image>/Filters/Animation/Animators") diff --git a/plug-ins/script-fu/scripts/spyrogimp.scm b/plug-ins/script-fu/scripts/spyrogimp.scm new file mode 100644 index 0000000..0a1e40c --- /dev/null +++ b/plug-ins/script-fu/scripts/spyrogimp.scm @@ -0,0 +1,352 @@ +; spyrogimp.scm -*-scheme-*- +; Draws Spirographs, Epitrochoids and Lissajous Curves. +; More info at http://www.wisdom.weizmann.ac.il/~elad/spyrogimp/ +; Version 1.2 +; +; Copyright (C) 2003 by Elad Shahar <elad@wisdom.weizmann.ac.il> +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +; This routine is invoked by a dialog. +; It is the main routine in this file. +(define (script-fu-spyrogimp img drw + type shape + oteeth iteeth + margin hole-ratio start-angle + tool brush + color-method color grad) + + ; Internal function to draw the spyro. + (define (script-fu-spyrogimp-internal img drw + x1 y1 x2 y2 ; Bounding box. + type ; = 0 (Spirograph), 1 (Epitrochoid), 2(Lissajous) . + shape ; = 0 (Circle), 1 (Frame), >2 (Polygons) . + oteeth iteeth ; Outer and inner teeth. + margin hole-ratio + start-angle ; 0 <= start-angle < 360 . + tool ; = 0 (Pencil), 1 (Brush), 2 (Airbrush) . + brush + color-method ; = 0 (Single color), 1 (Grad. Loop Sawtooth), + ; 2 (Grad. Loop triangle) . + color ; Used when color-method = Single color . + grad ; Gradient used in Gradient color methods. + ) + + + ; This function returns a list of samples according to the gradient. + (define (get-gradient steps color-method grad) + (if (= color-method 1) + ; option 1 + ; Just return the gradient + (gimp-gradient-get-uniform-samples grad (min steps 50) FALSE) + + ; option 2 + ; The returned list is such that the gradient appears two times, once + ; in the normal order and once in reverse. This way there are no color + ; jumps if we go beyond the edge + (let* ( + ; Sample the gradient into array "gr". + (gr (gimp-gradient-get-uniform-samples grad + (/ (min steps 50) 2) + FALSE)) + + (grn (car gr)) ; length of sample array. + (gra (cadr gr)) ; array of color samples (R1,G1,B1,A1, R2,....) + + ; Allocate array gra-new of size (2 * grn) - 8, + ; but since each 4 items is actually one (RGBA) tuple, + ; it contains 2x - 2 entries. + (grn-new (+ grn grn -8)) + (gra-new (cons-array grn-new 'double)) + + (gr-index 0) + (gr-index2 0) + ) + + ; Copy original array gra to gra_new. + (while (< gr-index grn) + (aset gra-new gr-index (aref gra gr-index)) + (set! gr-index (+ 1 gr-index)) + ) + + ; Copy second time, but in reverse + (set! gr-index2 (- gr-index 8)) + (while (< gr-index grn-new) + (aset gra-new gr-index (aref gra gr-index2)) + (set! gr-index (+ 1 gr-index)) + (set! gr-index2 (+ 1 gr-index2)) + + (if (= (fmod gr-index 4) 0) + (set! gr-index2 (- gr-index2 8)) + ) + ) + + ; Return list. + (list grn-new gra-new) + ) + ) + ) + + + (let* ( + (steps (+ 1 (lcm oteeth iteeth))) + (*points* (cons-array (* steps 2) 'double)) + + (ot 0) ; current outer tooth + (cx 0) ; Current x,y + (cy 0) + + ; If its a polygon or frame, how many sides does it have. + (poly (if (= shape 1) 4 ; A frame has four sides. + (if (> shape 1) (+ shape 1) 0))) + + (2pi (* 2 *pi*)) + + (drw-width (- x2 x1)) + (drw-height (- y2 y1)) + (half-width (/ drw-width 2)) + (half-height (/ drw-height 2)) + (midx (+ x1 half-width)) + (midy (+ y1 half-height)) + + (hole (* hole-ratio + (- (/ (min drw-width drw-height) 2) margin) + ) + ) + (irad (+ hole margin)) + + (radx (- half-width irad)) ; + (rady (- half-height irad)) ; + + (gradt (get-gradient steps color-method grad)) + (grada (cadr gradt)) ; Gradient array. + (gradn (car gradt)) ; Number of entries of gradients. + + ; Indexes + (grad-index 0) ; for array: grada + (point-index 0) ; for array: *points* + (index 0) + ) + + ; Do one step of the loop. + (define (calc-and-step!) + (let* ( + (oangle (* 2pi (/ ot oteeth)) ) + (shifted-oangle (+ oangle (* 2pi (/ start-angle 360))) ) + (xfactor (cos shifted-oangle)) + (yfactor (sin shifted-oangle)) + (lenfactor 1) + (ofactor (/ (+ oteeth iteeth) iteeth)) + + ; The direction of the factor changes according + ; to whether the type is a sypro or an epitcorhoid. + (mfactor (if (= type 0) (- ofactor) ofactor)) + ) + + ; If we are drawing a polygon then compute a contortion + ; factor "lenfactor" which deforms the standard circle. + (if (> poly 2) + (let* ( + (pi4 (/ *pi* poly)) + (pi2 (* pi4 2)) + + (oanglemodpi2 (fmod (+ oangle + (if (= 1 (fmod poly 2)) + 0 ;(/ pi4 2) + 0 + ) + ) + pi2)) + ) + + (set! lenfactor (/ ( if (= shape 1) 1 (cos pi4) ) + (cos + (if (< oanglemodpi2 pi4) + oanglemodpi2 + (- pi2 oanglemodpi2) + ) + ) + ) + ) + ) + ) + + (if (= type 2) + (begin ; Lissajous + (set! cx (+ midx + (* half-width (cos shifted-oangle)) )) + (set! cy (+ midy + (* half-height (cos (* mfactor oangle))) )) + ) + (begin ; Spyrograph or Epitrochoid + (set! cx (+ midx + (* radx xfactor lenfactor) + (* hole (cos (* mfactor oangle) ) ) )) + (set! cy (+ midy + (* rady yfactor lenfactor) + (* hole (sin (* mfactor oangle) ) ) )) + ) + ) + + ;; Advance teeth + (set! ot (+ ot 1)) + ) + ) + + + ;; Draw all the points in *points* with appropriate tool. + (define (flush-points len) + (if (= tool 0) + (gimp-pencil drw len *points*) ; Use pencil + (if (= tool 1) + (gimp-paintbrush-default drw len *points*); use paintbrush + (gimp-airbrush-default drw len *points*) ; use airbrush + ) + ) + + ; Reset points array, but copy last point to first + ; position so it will connect the next time. + (aset *points* 0 (aref *points* (- point-index 2))) + (aset *points* 1 (aref *points* (- point-index 1))) + (set! point-index 2) + ) + + ;; + ;; Execution starts here. + ;; + + (gimp-context-push) + + (gimp-image-undo-group-start img) + + ; Set new color, brush, opacity, paint mode. + (gimp-context-set-foreground color) + (gimp-context-set-brush (car brush)) + (gimp-context-set-opacity (car (cdr brush))) + (gimp-context-set-paint-mode (car (cdr (cdr (cdr brush))))) + + (gimp-progress-set-text _"Rendering Spyro") + + (while (< index steps) + + (calc-and-step!) + + (aset *points* point-index cx) + (aset *points* (+ point-index 1) cy) + (set! point-index (+ point-index 2)) + + ; Change color and draw points if using gradient. + (if (< 0 color-method) ; use gradient. + (if (< (/ (+ grad-index 4) gradn) (/ index steps)) + (begin + (gimp-context-set-foreground + (list + (* 255 (aref grada grad-index)) + (* 255 (aref grada (+ 1 grad-index)) ) + (* 255 (aref grada (+ 2 grad-index)) ) + ) + ) + (gimp-context-set-opacity (* 100 (aref grada (+ 3 grad-index) ) ) ) + (set! grad-index (+ 4 grad-index)) + + ; Draw points + (flush-points point-index) + ) + ) + ) + + (set! index (+ index 1)) + + (if (= 0 (modulo index 16)) + (gimp-progress-update (/ index steps)) + ) + ) + + ; Draw remaining points. + (flush-points point-index) + + (gimp-progress-update 1.0) + + (gimp-image-undo-group-end img) + (gimp-displays-flush) + + (gimp-context-pop) + ) + ) + + (let* ( + ; Get current selection to determine where to draw. + (bounds (cdr (gimp-selection-bounds img))) + (x1 (car bounds)) + (y1 (cadr bounds)) + (x2 (caddr bounds)) + (y2 (car (cdddr bounds))) + ) + + (set! oteeth (trunc (+ oteeth 0.5))) + (set! iteeth (trunc (+ iteeth 0.5))) + + (script-fu-spyrogimp-internal img drw + x1 y1 x2 y2 + type shape + oteeth iteeth + margin hole-ratio start-angle + tool brush + color-method color grad) + ) +) + + + +(script-fu-register "script-fu-spyrogimp" + _"_Spyrogimp (older script-fu version)..." + _"This procedure is deprecated! Use 'plug-in-spyrogimp' instead." + "Elad Shahar <elad@wisdom.weizmann.ac.il>" + "Elad Shahar" + "June 2003" + "RGB*, INDEXED*, GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + + SF-OPTION _"Type" '(_"Spyrograph" + _"Epitrochoid" + _"Lissajous") + SF-OPTION _"Shape" '(_"Circle" + _"Frame" + _"Triangle" + _"Square" + _"Pentagon" + _"Hexagon" + _"Polygon: 7 sides" + _"Polygon: 8 sides" + _"Polygon: 9 sides" + _"Polygon: 10 sides") + SF-ADJUSTMENT _"Outer teeth" '(86 1 120 1 10 0 0) + SF-ADJUSTMENT _"Inner teeth" '(70 1 120 1 10 0 0) + SF-ADJUSTMENT _"Margin (pixels)" '(0 -10000 10000 1 10 0 1) + SF-ADJUSTMENT _"Hole ratio" '(0.4 0.0 1.0 0.01 0.1 2 0) + SF-ADJUSTMENT _"Start angle" '(0 0 359 1 10 0 0) + + SF-OPTION _"Tool" '(_"Pencil" + _"Brush" + _"Airbrush") + SF-BRUSH _"Brush" '("Circle (01)" 100 -1 0) + + SF-OPTION _"Color method" '(_"Solid Color" + _"Gradient: Loop Sawtooth" + _"Gradient: Loop Triangle") + SF-COLOR _"Color" "black" + SF-GRADIENT _"Gradient" "Deep Sea" +) diff --git a/plug-ins/script-fu/scripts/test-sphere.scm b/plug-ins/script-fu/scripts/test-sphere.scm new file mode 100644 index 0000000..763e9b0 --- /dev/null +++ b/plug-ins/script-fu/scripts/test-sphere.scm @@ -0,0 +1,307 @@ +; This is a a test script to show and test the possibilities of the +; Script-Fu parameter API. +; +; ---------------------------------------------------------------------- +; SF-ADJUSTMENT +; is only useful in interactive mode, if you call a script from +; the console, it acts just like a normal SF-VALUE +; In interactive mode it creates an adjustment widget in the dialog. +; +; Usage: +; SF-ADJUSTMENT "label" '(value lower upper step_inc page_inc digits type) +; +; type is one of: SF-SLIDER(0), SF-SPINNER(1) +; +; ---------------------------------------------------------------------- +; SF-COLOR +; creates a color button in the dialog. It accepts either a list of three +; values for the red, green and blue components or a color name in CSS +; notatation +; +; Usage: +; SF-COLOR "label" '(red green blue) +; SF-COLOR "label" "color" +; +; ---------------------------------------------------------------------- +; SF-FONT +; creates a font-selection widget in the dialog. It returns a fontname as +; a string. There are two new gimp-text procedures to ease the use of this +; return parameter: +; +; (gimp-text-fontname image drawable +; x-pos y-pos text border antialias size unit font) +; (gimp-text-get-extents-fontname text size unit font)) +; +; where font is the fontname you get. The size specified in the fontname +; is silently ignored. It is only used in the font-selector. So you are +; asked to set it to a useful value (24 pixels is a good choice) when +; using SF-FONT. +; +; Usage: +; SF-FONT "label" "fontname" +; +; ---------------------------------------------------------------------- +; SF-BRUSH +; is only useful in interactive mode. It will create a widget in the control +; dialog. The widget consists of a preview area (which when pressed will +; produce a popup preview ) and a button with the "..." label. The button will +; popup a dialog where brushes can be selected and each of the +; characteristics of the brush can be modified. +; +; The actual value returned when the script is invoked is a list +; consisting of Brush name, opacity, spacing and brush mode in the same +; units as passed in as the default value. +; +; Usage: +; SF-BRUSH "Brush" '("Circle (03)" 100 44 0) +; +; Here the brush dialog will be popped up with a default brush of Circle (03) +; opacity 100 spacing 44 and paint mode of Normal (value 0). +; If this selection was unchanged the value passed to the function as a +; parameter would be '("Circle (03)" 100 44 0). +; +; ---------------------------------------------------------------------- +; SF-PATTERN +; Only useful in interactive mode. It will create a widget in the control +; dialog. The widget consists of a preview area (which when pressed will +; produce a popup preview ) and a button with the "..." label. The button will +; popup a dialog where patterns can be selected. +; +; Usage: +; SF-PATTERN "Pattern" "Maple Leaves" +; +; The value returned when the script is invoked is a string containing the +; pattern name. If the above selection was not altered the string would +; contain "Maple Leaves" +; +; ---------------------------------------------------------------------- +; SF-GRADIENT +; Only useful in interactive mode. It will create a widget in the control +; dialog. The widget consists of a button containing a preview of the selected +; gradient. If the button is pressed a gradient selection dialog will popup. +; +; Usage: +; SF-GRADIENT "Gradient" "Deep Sea" +; +; The value returned when the script is invoked is a string containing the +; gradient name. If the above selection was not altered the string would +; contain "Deep Sea" +; +; ---------------------------------------------------------------------- +; SF-PALETTE +; Only useful in interactive mode. It will create a widget in the control +; dialog. The widget consists of a button containing a preview of the selected +; palette. If the button is pressed a palette selection dialog will popup. +; +; Usage: +; SF-PALETTE "Palette" "Named Colors" +; +; The value returned when the script is invoked is a string containing the +; palette name. If the above selection was not altered the string would +; contain "Named Colors" +; +; ---------------------------------------------------------------------- +; SF-FILENAME +; Only useful in interactive mode. It will create a widget in the control +; dialog. The widget consists of a button containing the name of a file. +; If the button is pressed a file selection dialog will popup. +; +; Usage: +; SF-FILENAME "Environment Map" +; (string-append "" gimp-data-directory "/scripts/beavis.jpg") +; +; The value returned when the script is invoked is a string containing the +; filename. +; +; ---------------------------------------------------------------------- +; SF-DIRNAME +; Only useful in interactive mode. Very similar to SF-FILENAME, but the +; created widget allows to choose a directory instead of a file. +; +; Usage: +; SF-DIRNAME "Image Directory" "/var/tmp/images" +; +; The value returned when the script is invoked is a string containing the +; dirname. +; +; ---------------------------------------------------------------------- +; SF-OPTION +; Only useful in interactive mode. It will create a widget in the control +; dialog. The widget is a combo-box showing the options that are passed +; as a list. The first option is the default choice. +; +; Usage: +; SF-OPTION "Orientation" '("Horizontal" "Vertical") +; +; The value returned when the script is invoked is the number of the +; chosen option, where the option first is counted as 0. +; +; ---------------------------------------------------------------------- +; SF-ENUM +; Only useful in interactive mode. It will create a widget in the control +; dialog. The widget is a combo-box showing all enum values for the given +; enum type. This has to be the name of a registered enum, without the +; "Gimp" prefix. The second parameter specifies the default value, using +; the enum value's nick. +; +; Usage: +; SF-ENUM "Interpolation" '("InterpolationType" "linear") +; +; The value returned when the script is invoked corresponds to chosen +; enum value. +; +; ---------------------------------------------------------------------- + + +(define (script-fu-test-sphere radius + light + shadow + bg-color + sphere-color + brush + text + multi-text + pattern + gradient + gradient-reverse + font + size + unused-palette + unused-filename + unused-orientation + unused-interpolation + unused-dirname + unused-image + unused-layer + unused-channel + unused-drawable) + (let* ( + (width (* radius 3.75)) + (height (* radius 2.5)) + (img (car (gimp-image-new width height RGB))) + (drawable (car (gimp-layer-new img width height RGB-IMAGE + "Sphere Layer" 100 LAYER-MODE-NORMAL))) + (radians (/ (* light *pi*) 180)) + (cx (/ width 2)) + (cy (/ height 2)) + (light-x (+ cx (* radius (* 0.6 (cos radians))))) + (light-y (- cy (* radius (* 0.6 (sin radians))))) + (light-end-x (+ cx (* radius (cos (+ *pi* radians))))) + (light-end-y (- cy (* radius (sin (+ *pi* radians))))) + (offset (* radius 0.1)) + (text-extents (gimp-text-get-extents-fontname multi-text + size PIXELS + font)) + (x-position (- cx (/ (car text-extents) 2))) + (y-position (- cy (/ (cadr text-extents) 2))) + (shadow-w 0) + (shadow-x 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + (gimp-context-set-foreground sphere-color) + (gimp-context-set-background bg-color) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + (gimp-context-set-background '(20 20 20)) + + (if (and + (or (and (>= light 45) (<= light 75)) + (and (<= light 135) (>= light 105))) + (= shadow TRUE)) + (let ((shadow-w (* (* radius 2.5) (cos (+ *pi* radians)))) + (shadow-h (* radius 0.5)) + (shadow-x cx) + (shadow-y (+ cy (* radius 0.65)))) + (if (< shadow-w 0) + (begin (set! shadow-x (+ cx shadow-w)) + (set! shadow-w (- shadow-w)))) + + (gimp-context-set-feather TRUE) + (gimp-context-set-feather-radius 7.5 7.5) + (gimp-image-select-ellipse img CHANNEL-OP-REPLACE shadow-x shadow-y shadow-w shadow-h) + (gimp-context-set-pattern pattern) + (gimp-drawable-edit-fill drawable FILL-PATTERN))) + + (gimp-context-set-feather FALSE) + (gimp-image-select-ellipse img CHANNEL-OP-REPLACE (- cx radius) (- cy radius) + (* 2 radius) (* 2 radius)) + + (gimp-context-set-gradient-fg-bg-rgb) + (gimp-drawable-edit-gradient-fill drawable + GRADIENT-RADIAL offset + FALSE 0 0 + TRUE + light-x light-y + light-end-x light-end-y) + + (gimp-selection-none img) + + (gimp-image-select-ellipse img CHANNEL-OP-REPLACE 10 10 50 50) + + (gimp-context-set-gradient gradient) + (gimp-context-set-gradient-reverse gradient-reverse) + (gimp-drawable-edit-gradient-fill drawable + GRADIENT-LINEAR offset + FALSE 0 0 + TRUE + 10 10 + 30 60) + + (gimp-selection-none img) + + (gimp-context-set-foreground '(0 0 0)) + (gimp-floating-sel-anchor (car (gimp-text-fontname img drawable + x-position y-position + multi-text + 0 TRUE + size PIXELS + font))) + + (gimp-image-undo-enable img) + (gimp-display-new img) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-test-sphere" + _"_Sphere..." + "Simple script to test and show the usage of the new Script-Fu API extensions." + "Spencer Kimball, Sven Neumann" + "Spencer Kimball" + "1996, 1998" + "" + SF-ADJUSTMENT "Radius (in pixels)" (list 100 1 5000 1 10 0 SF-SPINNER) + SF-ADJUSTMENT "Lighting (degrees)" (list 45 0 360 1 10 1 SF-SLIDER) + SF-TOGGLE "Shadow" TRUE + SF-COLOR "Background color" "white" + SF-COLOR "Sphere color" "red" + SF-BRUSH "Brush" '("2. Hardness 100" 100 44 0) + SF-STRING "Text" "Tiny-Fu rocks!" + SF-TEXT "Multi-line text" "Hello,\nWorld!" + SF-PATTERN "Pattern" "Maple Leaves" + SF-GRADIENT "Gradient" "Deep Sea" + SF-TOGGLE "Gradient reverse" FALSE + SF-FONT "Font" "Agate" + SF-ADJUSTMENT "Font size (pixels)" '(50 1 1000 1 10 0 1) + SF-PALETTE "Palette" "Default" + SF-FILENAME "Environment map" + (string-append gimp-data-directory + "/scripts/images/beavis.jpg") + SF-OPTION "Orientation" '("Horizontal" + "Vertical") + SF-ENUM "Interpolation" '("InterpolationType" "linear") + SF-DIRNAME "Output directory" "/var/tmp/" + SF-IMAGE "Image" -1 + SF-LAYER "Layer" -1 + SF-CHANNEL "Channel" -1 + SF-DRAWABLE "Drawable" -1 + SF-VECTORS "Vectors" -1 +) + +(script-fu-menu-register "script-fu-test-sphere" + "<Image>/Filters/Languages/Script-Fu/Test") diff --git a/plug-ins/script-fu/scripts/tileblur.scm b/plug-ins/script-fu/scripts/tileblur.scm new file mode 100644 index 0000000..4be7a6c --- /dev/null +++ b/plug-ins/script-fu/scripts/tileblur.scm @@ -0,0 +1,83 @@ +; Chris Gutteridge (cjg@ecs.soton.ac.uk) +; At ECS Dept, University of Southampton, England. + +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-tile-blur inImage inLayer inRadius inVert inHoriz inType) + + (let* ( + (theImage inImage) + (theLayer inLayer) + (theHeight (car (gimp-drawable-height theLayer))) + (theWidth (car (gimp-drawable-width theLayer))) + ) + + (define (pasteat xoff yoff) + (let ((theFloat (car(gimp-edit-paste theLayer 0)))) + (gimp-layer-set-offsets theFloat (* xoff theWidth) (* yoff theHeight) ) + (gimp-floating-sel-anchor theFloat) + ) + ) + + (gimp-context-push) + (gimp-context-set-feather FALSE) + (gimp-image-undo-group-start theImage) + + (gimp-layer-resize theLayer (* 3 theWidth) (* 3 theHeight) 0 0) + + (gimp-image-select-rectangle theImage CHANNEL-OP-REPLACE 0 0 theWidth theHeight) + (gimp-edit-cut theLayer) + + (gimp-selection-none theImage) + (gimp-layer-set-offsets theLayer theWidth theHeight) + + (pasteat 1 1) (pasteat 1 2) (pasteat 1 3) + (pasteat 2 1) (pasteat 2 2) (pasteat 2 3) + (pasteat 3 1) (pasteat 3 2) (pasteat 3 3) + + (gimp-selection-none theImage) + (if (= inType 0) + (plug-in-gauss-iir RUN-NONINTERACTIVE + theImage theLayer inRadius inHoriz inVert) + (plug-in-gauss-rle RUN-NONINTERACTIVE + theImage theLayer inRadius inHoriz inVert) + ) + + (gimp-layer-resize theLayer + theWidth theHeight (- 0 theWidth) (- 0 theHeight)) + (gimp-layer-set-offsets theLayer 0 0) + (gimp-image-undo-group-end theImage) + (gimp-displays-flush) + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-tile-blur" + _"_Tileable Blur..." + _"Blur the edges of an image so the result tiles seamlessly" + "Chris Gutteridge" + "1998, Chris Gutteridge / ECS dept, University of Southampton, England." + "25th April 1998" + "RGB*" + SF-IMAGE "The Image" 0 + SF-DRAWABLE "The Layer" 0 + SF-ADJUSTMENT _"Radius" '(5 0 128 1 1 0 0) + SF-TOGGLE _"Blur vertically" TRUE + SF-TOGGLE _"Blur horizontally" TRUE + SF-OPTION _"Blur type" '(_"IIR" _"RLE") +) + +(script-fu-menu-register "script-fu-tile-blur" + "<Image>/Filters/Blur") diff --git a/plug-ins/script-fu/scripts/ts-helloworld.scm b/plug-ins/script-fu/scripts/ts-helloworld.scm new file mode 100644 index 0000000..2c04105 --- /dev/null +++ b/plug-ins/script-fu/scripts/ts-helloworld.scm @@ -0,0 +1,65 @@ +; "Hello, World" Test v1.00 February 29, 2004 +; by Kevin Cozens <kcozens@interlog.com> +; +; Creates an image with the text "Hello, World!" +; This was the first TinyScheme based script ever created and run for the +; 2.x version of GIMP. + +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; Tiny-Fu first successfully ran this script at 2:07am on March 6, 2004. + +(define (script-fu-helloworld text font size color) + (let* ( + (width 10) + (height 10) + (img (car (gimp-image-new width height RGB))) + (text-layer) + ) + + (gimp-context-push) + + (gimp-image-undo-disable img) + (gimp-context-set-foreground color) + + (set! text-layer (car (gimp-text-fontname img -1 0 0 text 10 TRUE size PIXELS font))) + (set! width (car (gimp-drawable-width text-layer))) + (set! height (car (gimp-drawable-height text-layer))) + (gimp-image-resize img width height 0 0) + + (gimp-image-undo-enable img) + (gimp-display-new img) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-helloworld" + "_Hello World..." + "Creates an image with a user specified text string." + "Kevin Cozens <kcozens@interlog.com>" + "Kevin Cozens" + "February 29, 2004" + "" + SF-STRING "Text string" "Hello, World!" + SF-FONT "Font" "Sans" + SF-ADJUSTMENT "Font size (pixels)" '(100 2 1000 1 10 0 1) + SF-COLOR "Color" '(0 0 0) +) + +(script-fu-menu-register "script-fu-helloworld" + "<Image>/Filters/Languages/Script-Fu/Test") diff --git a/plug-ins/script-fu/scripts/unsharp-mask.scm b/plug-ins/script-fu/scripts/unsharp-mask.scm new file mode 100644 index 0000000..77daf82 --- /dev/null +++ b/plug-ins/script-fu/scripts/unsharp-mask.scm @@ -0,0 +1,84 @@ +;;; unsharp-mask.scm +;;; Time-stamp: <1998/11/17 13:18:39 narazaki@gimp.org> +;;; Author: Narazaki Shuji <narazaki@gimp.org> +;;; Version 0.8 + +(define (script-fu-unsharp-mask img drw mask-size mask-opacity) + (let* ( + (drawable-width (car (gimp-drawable-width drw))) + (drawable-height (car (gimp-drawable-height drw))) + (new-image (car (gimp-image-new drawable-width drawable-height RGB))) + (original-layer (car (gimp-layer-new new-image + drawable-width drawable-height + RGB-IMAGE "Original" + 100 LAYER-MODE-NORMAL))) + (original-layer-for-darker 0) + (original-layer-for-lighter 0) + (blurred-layer-for-darker 0) + (blurred-layer-for-lighter 0) + (darker-layer 0) + (lighter-layer 0) + ) + + (gimp-selection-all img) + (gimp-edit-copy drw) + + (gimp-image-undo-disable new-image) + + (gimp-image-insert-layer new-image original-layer 0 0) + (gimp-floating-sel-anchor + (car (gimp-edit-paste original-layer FALSE))) + + (set! original-layer-for-darker (car (gimp-layer-copy original-layer TRUE))) + (set! original-layer-for-lighter (car (gimp-layer-copy original-layer TRUE))) + (set! blurred-layer-for-darker (car (gimp-layer-copy original-layer TRUE))) + (gimp-item-set-visible original-layer FALSE) + (gimp-display-new new-image) + + ;; make darker mask + (gimp-image-insert-layer new-image blurred-layer-for-darker 0 -1) + (plug-in-gauss-iir RUN-NONINTERACTIVE + new-image blurred-layer-for-darker mask-size TRUE TRUE) + (set! blurred-layer-for-lighter + (car (gimp-layer-copy blurred-layer-for-darker TRUE))) + (gimp-image-insert-layer new-image original-layer-for-darker 0 -1) + (gimp-layer-set-mode original-layer-for-darker LAYER-MODE-SUBTRACT) + (set! darker-layer + (car (gimp-image-merge-visible-layers new-image CLIP-TO-IMAGE))) + (gimp-item-set-name darker-layer "darker mask") + (gimp-item-set-visible darker-layer FALSE) + + ;; make lighter mask + (gimp-image-insert-layer new-image original-layer-for-lighter 0 -1) + (gimp-image-insert-layer new-image blurred-layer-for-lighter 0 -1) + (gimp-layer-set-mode blurred-layer-for-lighter LAYER-MODE-SUBTRACT) + (set! lighter-layer + (car (gimp-image-merge-visible-layers new-image CLIP-TO-IMAGE))) + (gimp-item-set-name lighter-layer "lighter mask") + + ;; combine them + (gimp-item-set-visible original-layer TRUE) + (gimp-layer-set-mode darker-layer LAYER-MODE-SUBTRACT) + (gimp-layer-set-opacity darker-layer mask-opacity) + (gimp-item-set-visible darker-layer TRUE) + (gimp-layer-set-mode lighter-layer LAYER-MODE-ADDITION) + (gimp-layer-set-opacity lighter-layer mask-opacity) + (gimp-item-set-visible lighter-layer TRUE) + + (gimp-image-undo-enable new-image) + (gimp-displays-flush) + ) +) + +(script-fu-register "script-fu-unsharp-mask" + "Unsharp Mask..." + "Make a new image from the current layer by applying the unsharp mask method" + "Shuji Narazaki <narazaki@gimp.org>" + "Shuji Narazaki" + "1997,1998" + "" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable to apply" 0 + SF-ADJUSTMENT _"Mask size" '(5 1 100 1 1 0 1) + SF-ADJUSTMENT _"Mask opacity" '(50 0 100 1 1 0 1) +) diff --git a/plug-ins/script-fu/scripts/waves-anim.scm b/plug-ins/script-fu/scripts/waves-anim.scm new file mode 100644 index 0000000..4e43d98 --- /dev/null +++ b/plug-ins/script-fu/scripts/waves-anim.scm @@ -0,0 +1,110 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; waves-anim.scm version 1.01 1997/12/13 +; +; CHANGE-LOG: +; 1.00 - initial release +; 1.01 - some code cleanup, no real changes +; +; Copyright (C) 1997 Sven Neumann <sven@gimp.org> +; +; +; Makes a copy of your image and creates an animation of the active layer +; as if a stone was thrown into the image. The animation may be saved with +; the gif-plug-in. + +(define (script-fu-waves-anim img + drawable + amplitude + wavelength + num-frames + invert) + (let* ((amplitude (max 0 amplitude)) + (wavelength (max 0 wavelength)) + (num-frames (max 1 num-frames)) + (remaining-frames num-frames) + (phase 0) + (phaseshift (/ 360 num-frames)) + (image (car (gimp-image-duplicate img))) + (source-layer (car (gimp-image-get-active-layer image)))) + + (gimp-image-undo-disable image) + + (if (= invert TRUE) + (set! phaseshift (- 0 phaseshift))) + + (while (> remaining-frames 1) + (let* ( + (waves-layer (car (gimp-layer-copy source-layer TRUE))) + (layer-name (string-append "Frame " + (number->string + (- (+ num-frames 2) + remaining-frames) 10 + ) + " (replace)")) + ) + (gimp-layer-set-lock-alpha waves-layer FALSE) + (gimp-image-insert-layer image waves-layer 0 -1) + (gimp-item-set-name waves-layer layer-name) + + (plug-in-waves RUN-NONINTERACTIVE + image + waves-layer + amplitude + phase + wavelength + 0 + FALSE) + + (set! remaining-frames (- remaining-frames 1)) + (set! phase (- phase phaseshift)) + ) + ) + + (gimp-item-set-name source-layer "Frame 1") + (plug-in-waves RUN-NONINTERACTIVE + image + source-layer + amplitude + phase + wavelength + 0 + FALSE) + + (gimp-image-undo-enable image) + (gimp-display-new image) + ) +) + +(script-fu-register "script-fu-waves-anim" + _"_Waves..." + _"Create a multi-layer image with an effect like a stone was thrown into the current image" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "1997/13/12" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Amplitude" '(10 1 101 1 10 1 0) + SF-ADJUSTMENT _"Wavelength" '(10 0.1 100 1 10 1 0) + SF-ADJUSTMENT _"Number of frames" '(6 1 512 1 10 0 1) + SF-TOGGLE _"Invert direction" FALSE +) + +(script-fu-menu-register "script-fu-waves-anim" + "<Image>/Filters/Animation/Animators") diff --git a/plug-ins/script-fu/scripts/weave.scm b/plug-ins/script-fu/scripts/weave.scm new file mode 100644 index 0000000..81fd0a7 --- /dev/null +++ b/plug-ins/script-fu/scripts/weave.scm @@ -0,0 +1,415 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; Weave script --- make an image look as if it were woven +; Copyright (C) 1997 Federico Mena Quintero +; federico@nuclecu.unam.mx +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +; Copies the specified rectangle from/to the specified drawable + +(define (copy-rectangle img + drawable + x1 + y1 + width + height + dest-x + dest-y) + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE x1 y1 width height) + (gimp-edit-copy drawable) + (let ((floating-sel (car (gimp-edit-paste drawable FALSE)))) + (gimp-layer-set-offsets floating-sel dest-x dest-y) + (gimp-floating-sel-anchor floating-sel)) + (gimp-selection-none img)) + +; Creates a single weaving tile + +(define (create-weave-tile ribbon-width + ribbon-spacing + shadow-darkness + shadow-depth) + (let* ((tile-size (+ (* 2 ribbon-width) (* 2 ribbon-spacing))) + (darkness (* 255 (/ (- 100 shadow-darkness) 100))) + (img (car (gimp-image-new tile-size tile-size RGB))) + (drawable (car (gimp-layer-new img tile-size tile-size RGB-IMAGE + "Weave tile" 100 LAYER-MODE-NORMAL)))) + + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + + ; Create main horizontal ribbon + + (gimp-context-set-foreground '(255 255 255)) + (gimp-context-set-background (list darkness darkness darkness)) + + (gimp-image-select-rectangle img + CHANNEL-OP-REPLACE + 0 + ribbon-spacing + (+ (* 2 ribbon-spacing) ribbon-width) + ribbon-width) + + (gimp-context-set-gradient-fg-bg-rgb) + (gimp-drawable-edit-gradient-fill drawable + GRADIENT-BILINEAR (- 100 shadow-depth) + FALSE 0 0 + TRUE + (/ (+ (* 2 ribbon-spacing) ribbon-width -1) 2) 0 + 0 0) + + ; Create main vertical ribbon + + (gimp-image-select-rectangle img + CHANNEL-OP-REPLACE + (+ (* 2 ribbon-spacing) ribbon-width) + 0 + ribbon-width + (+ (* 2 ribbon-spacing) ribbon-width)) + + (gimp-drawable-edit-gradient-fill drawable + GRADIENT-BILINEAR (- 100 shadow-depth) + FALSE 0 0 + TRUE + 0 (/ (+ (* 2 ribbon-spacing) ribbon-width -1) 2) + 0 0) + + ; Create the secondary horizontal ribbon + + (copy-rectangle img + drawable + 0 + ribbon-spacing + (+ ribbon-width ribbon-spacing) + ribbon-width + (+ ribbon-width ribbon-spacing) + (+ (* 2 ribbon-spacing) ribbon-width)) + + (copy-rectangle img + drawable + (+ ribbon-width ribbon-spacing) + ribbon-spacing + ribbon-spacing + ribbon-width + 0 + (+ (* 2 ribbon-spacing) ribbon-width)) + + ; Create the secondary vertical ribbon + + (copy-rectangle img + drawable + (+ (* 2 ribbon-spacing) ribbon-width) + 0 + ribbon-width + (+ ribbon-width ribbon-spacing) + ribbon-spacing + (+ ribbon-width ribbon-spacing)) + + (copy-rectangle img + drawable + (+ (* 2 ribbon-spacing) ribbon-width) + (+ ribbon-width ribbon-spacing) + ribbon-width + ribbon-spacing + ribbon-spacing + 0) + + ; Done + + (gimp-image-undo-enable img) + (list img drawable))) + +; Creates a complete weaving mask + +(define (create-weave width + height + ribbon-width + ribbon-spacing + shadow-darkness + shadow-depth) + (let* ((tile (create-weave-tile ribbon-width ribbon-spacing shadow-darkness + shadow-depth)) + (tile-img (car tile)) + (tile-layer (cadr tile)) + (weaving (plug-in-tile RUN-NONINTERACTIVE tile-img tile-layer width height TRUE))) + (gimp-image-delete tile-img) + weaving)) + +; Creates a single tile for masking + +(define (create-mask-tile ribbon-width + ribbon-spacing + r1-x1 + r1-y1 + r1-width + r1-height + r2-x1 + r2-y1 + r2-width + r2-height + r3-x1 + r3-y1 + r3-width + r3-height) + (let* ((tile-size (+ (* 2 ribbon-width) (* 2 ribbon-spacing))) + (img (car (gimp-image-new tile-size tile-size RGB))) + (drawable (car (gimp-layer-new img tile-size tile-size RGB-IMAGE + "Mask" 100 LAYER-MODE-NORMAL)))) + (gimp-image-undo-disable img) + (gimp-image-insert-layer img drawable 0 0) + + (gimp-context-set-background '(0 0 0)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + + (gimp-image-select-rectangle img CHANNEL-OP-REPLACE r1-x1 r1-y1 r1-width r1-height) + (gimp-image-select-rectangle img CHANNEL-OP-ADD r2-x1 r2-y1 r2-width r2-height) + (gimp-image-select-rectangle img CHANNEL-OP-ADD r3-x1 r3-y1 r3-width r3-height) + + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + (gimp-selection-none img) + + (gimp-image-undo-enable img) + + (list img drawable))) + +; Creates a complete mask image + +(define (create-mask final-width + final-height + ribbon-width + ribbon-spacing + r1-x1 + r1-y1 + r1-width + r1-height + r2-x1 + r2-y1 + r2-width + r2-height + r3-x1 + r3-y1 + r3-width + r3-height) + (let* ((tile (create-mask-tile ribbon-width ribbon-spacing + r1-x1 r1-y1 r1-width r1-height + r2-x1 r2-y1 r2-width r2-height + r3-x1 r3-y1 r3-width r3-height)) + (tile-img (car tile)) + (tile-layer (cadr tile)) + (mask (plug-in-tile RUN-NONINTERACTIVE tile-img tile-layer final-width final-height + TRUE))) + (gimp-image-delete tile-img) + mask)) + +; Creates the mask for horizontal ribbons + +(define (create-horizontal-mask ribbon-width + ribbon-spacing + final-width + final-height) + (create-mask final-width + final-height + ribbon-width + ribbon-spacing + 0 + ribbon-spacing + (+ (* 2 ribbon-spacing) ribbon-width) + ribbon-width + 0 + (+ (* 2 ribbon-spacing) ribbon-width) + ribbon-spacing + ribbon-width + (+ ribbon-width ribbon-spacing) + (+ (* 2 ribbon-spacing) ribbon-width) + (+ ribbon-width ribbon-spacing) + ribbon-width)) + +; Creates the mask for vertical ribbons + +(define (create-vertical-mask ribbon-width + ribbon-spacing + final-width + final-height) + (create-mask final-width + final-height + ribbon-width + ribbon-spacing + (+ (* 2 ribbon-spacing) ribbon-width) + 0 + ribbon-width + (+ (* 2 ribbon-spacing) ribbon-width) + ribbon-spacing + 0 + ribbon-width + ribbon-spacing + ribbon-spacing + (+ ribbon-width ribbon-spacing) + ribbon-width + (+ ribbon-width ribbon-spacing))) + +; Adds a threads layer at a certain orientation to the specified image + +(define (create-threads-layer img + width + height + length + density + orientation) + (let* ((drawable (car (gimp-layer-new img width height RGBA-IMAGE + "Threads" 100 LAYER-MODE-NORMAL))) + (dense (/ density 100.0))) + (gimp-image-insert-layer img drawable 0 -1) + (gimp-context-set-background '(255 255 255)) + (gimp-drawable-edit-fill drawable FILL-BACKGROUND) + (plug-in-noisify RUN-NONINTERACTIVE img drawable FALSE dense dense dense dense) + (plug-in-c-astretch RUN-NONINTERACTIVE img drawable) + (cond ((eq? orientation 'horizontal) + (plug-in-gauss-rle RUN-NONINTERACTIVE img drawable length TRUE FALSE)) + ((eq? orientation 'vertical) + (plug-in-gauss-rle RUN-NONINTERACTIVE img drawable length FALSE TRUE))) + (plug-in-c-astretch RUN-NONINTERACTIVE img drawable) + drawable)) + +(define (create-complete-weave width + height + ribbon-width + ribbon-spacing + shadow-darkness + shadow-depth + thread-length + thread-density + thread-intensity) + (let* ((weave (create-weave width height ribbon-width ribbon-spacing + shadow-darkness shadow-depth)) + (w-img (car weave)) + (w-layer (cadr weave)) + + (h-layer (create-threads-layer w-img width height thread-length + thread-density 'horizontal)) + (h-mask (car (gimp-layer-create-mask h-layer ADD-MASK-WHITE))) + + (v-layer (create-threads-layer w-img width height thread-length + thread-density 'vertical)) + (v-mask (car (gimp-layer-create-mask v-layer ADD-MASK-WHITE))) + + (hmask (create-horizontal-mask ribbon-width ribbon-spacing + width height)) + (hm-img (car hmask)) + (hm-layer (cadr hmask)) + + (vmask (create-vertical-mask ribbon-width ribbon-spacing width height)) + (vm-img (car vmask)) + (vm-layer (cadr vmask))) + + (gimp-layer-add-mask h-layer h-mask) + (gimp-selection-all hm-img) + (gimp-edit-copy hm-layer) + (gimp-image-delete hm-img) + (gimp-floating-sel-anchor (car (gimp-edit-paste h-mask FALSE))) + (gimp-layer-set-opacity h-layer thread-intensity) + (gimp-layer-set-mode h-layer LAYER-MODE-MULTIPLY) + + (gimp-layer-add-mask v-layer v-mask) + (gimp-selection-all vm-img) + (gimp-edit-copy vm-layer) + (gimp-image-delete vm-img) + (gimp-floating-sel-anchor (car (gimp-edit-paste v-mask FALSE))) + (gimp-layer-set-opacity v-layer thread-intensity) + (gimp-layer-set-mode v-layer LAYER-MODE-MULTIPLY) + + ; Uncomment this if you want to keep the weaving mask image + ; (gimp-display-new (car (gimp-image-duplicate w-img))) + + (list w-img + (car (gimp-image-flatten w-img))))) + +; The main weave function + +(define (script-fu-weave img + drawable + ribbon-width + ribbon-spacing + shadow-darkness + shadow-depth + thread-length + thread-density + thread-intensity) + (gimp-context-push) + (gimp-image-undo-group-start img) + + (let* ( + (d-img (car (gimp-item-get-image drawable))) + (d-width (car (gimp-drawable-width drawable))) + (d-height (car (gimp-drawable-height drawable))) + (d-offsets (gimp-drawable-offsets drawable)) + + (weaving (create-complete-weave d-width + d-height + ribbon-width + ribbon-spacing + shadow-darkness + shadow-depth + thread-length + thread-density + thread-intensity)) + (w-img (car weaving)) + (w-layer (cadr weaving)) + ) + + (gimp-context-set-paint-mode LAYER-MODE-NORMAL) + (gimp-context-set-opacity 100.0) + (gimp-context-set-feather FALSE) + + (gimp-selection-all w-img) + (gimp-edit-copy w-layer) + (gimp-image-delete w-img) + (let ((floating-sel (car (gimp-edit-paste drawable FALSE)))) + (gimp-layer-set-offsets floating-sel + (car d-offsets) + (cadr d-offsets)) + (gimp-layer-set-mode floating-sel LAYER-MODE-MULTIPLY) + (gimp-floating-sel-to-layer floating-sel) + ) + ) + (gimp-context-pop) + (gimp-image-undo-group-end img) + (gimp-displays-flush) +) + +(script-fu-register "script-fu-weave" + _"_Weave..." + _"Create a new layer filled with a weave effect to be used as an overlay or bump map" + "Federico Mena Quintero" + "Federico Mena Quintero" + "June 1997" + "RGB* GRAY*" + SF-IMAGE "Image to Weave" 0 + SF-DRAWABLE "Drawable to Weave" 0 + SF-ADJUSTMENT _"Ribbon width" '(30 0 256 1 10 1 1) + SF-ADJUSTMENT _"Ribbon spacing" '(10 0 256 1 10 1 1) + SF-ADJUSTMENT _"Shadow darkness" '(75 0 100 1 10 1 1) + SF-ADJUSTMENT _"Shadow depth" '(75 0 100 1 10 1 1) + SF-ADJUSTMENT _"Thread length" '(200 0 256 1 10 1 1) + SF-ADJUSTMENT _"Thread density" '(50 0 100 1 10 1 1) + SF-ADJUSTMENT _"Thread intensity" '(100 0 100 1 10 1 1) +) + +(script-fu-menu-register "script-fu-weave" + "<Image>/Filters/Artistic") diff --git a/plug-ins/script-fu/scripts/xach-effect.scm b/plug-ins/script-fu/scripts/xach-effect.scm new file mode 100644 index 0000000..ae83885 --- /dev/null +++ b/plug-ins/script-fu/scripts/xach-effect.scm @@ -0,0 +1,142 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; xach effect script +; Copyright (c) 1997 Adrian Likins +; aklikins@eos.ncsu.edu +; +; based on a idea by Xach Beane <xach@mint.net> +; +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +(define (script-fu-xach-effect image + drawable + hl-offset-x + hl-offset-y + hl-color + hl-opacity-comp + ds-color + ds-opacity + ds-blur + ds-offset-x + ds-offset-y + keep-selection) + (let* ( + (ds-blur (max ds-blur 0)) + (ds-opacity (min ds-opacity 100)) + (ds-opacity (max ds-opacity 0)) + (type (car (gimp-drawable-type-with-alpha drawable))) + (image-width (car (gimp-image-width image))) + (hl-opacity (list hl-opacity-comp hl-opacity-comp hl-opacity-comp)) + (image-height (car (gimp-image-height image))) + (active-selection 0) + (from-selection 0) + (theLayer 0) + (hl-layer 0) + (shadow-layer 0) + (mask 0) + ) + + (gimp-context-push) + (gimp-context-set-defaults) + + (gimp-image-undo-group-start image) + (gimp-layer-add-alpha drawable) + + (if (= (car (gimp-selection-is-empty image)) TRUE) + (begin + (gimp-image-select-item image CHANNEL-OP-REPLACE drawable) + (set! active-selection (car (gimp-selection-save image))) + (set! from-selection FALSE)) + (begin + (set! from-selection TRUE) + (set! active-selection (car (gimp-selection-save image))))) + + (set! hl-layer (car (gimp-layer-new image image-width image-height type _"Highlight" 100 LAYER-MODE-NORMAL))) + (gimp-image-insert-layer image hl-layer 0 -1) + + (gimp-selection-none image) + (gimp-drawable-edit-clear hl-layer) + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + + (gimp-context-set-background hl-color) + (gimp-drawable-edit-fill hl-layer FILL-BACKGROUND) + (gimp-selection-translate image hl-offset-x hl-offset-y) + (gimp-drawable-edit-fill hl-layer FILL-BACKGROUND) + (gimp-selection-none image) + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + + (set! mask (car (gimp-layer-create-mask hl-layer ADD-MASK-WHITE))) + (gimp-layer-add-mask hl-layer mask) + + (gimp-context-set-background hl-opacity) + (gimp-drawable-edit-fill mask FILL-BACKGROUND) + + (set! shadow-layer (car (gimp-layer-new image + image-width + image-height + type + _"Shadow" + ds-opacity + LAYER-MODE-NORMAL))) + (gimp-image-insert-layer image shadow-layer 0 -1) + (gimp-selection-none image) + (gimp-drawable-edit-clear shadow-layer) + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-selection-translate image ds-offset-x ds-offset-y) + (gimp-context-set-background ds-color) + (gimp-drawable-edit-fill shadow-layer FILL-BACKGROUND) + (gimp-selection-none image) + (plug-in-gauss-rle RUN-NONINTERACTIVE image shadow-layer ds-blur TRUE TRUE) + (gimp-image-select-item image CHANNEL-OP-REPLACE active-selection) + (gimp-drawable-edit-clear shadow-layer) + (gimp-image-lower-item image shadow-layer) + + (if (= keep-selection FALSE) + (gimp-selection-none image)) + + (gimp-image-set-active-layer image drawable) + (gimp-image-remove-channel image active-selection) + (gimp-image-undo-group-end image) + (gimp-displays-flush) + + (gimp-context-pop) + ) +) + +(script-fu-register "script-fu-xach-effect" + _"_Xach-Effect..." + _"Add a subtle translucent 3D effect to the selected region (or alpha)" + "Adrian Likins <adrian@gimp.org>" + "Adrian Likins" + "9/28/97" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Highlight X offset" '(-1 -100 100 1 10 0 1) + SF-ADJUSTMENT _"Highlight Y offset" '(-1 -100 100 1 10 0 1) + SF-COLOR _"Highlight color" "white" + SF-ADJUSTMENT _"Highlight opacity" '(66 0 255 1 10 0 0) + SF-COLOR _"Drop shadow color" "black" + SF-ADJUSTMENT _"Drop shadow opacity" '(100 0 100 1 10 0 0) + SF-ADJUSTMENT _"Drop shadow blur radius" '(12 0 255 1 10 0 1) + SF-ADJUSTMENT _"Drop shadow X offset" '(5 0 255 1 10 0 1) + SF-ADJUSTMENT _"Drop shadow Y offset" '(5 0 255 1 10 0 1) + SF-TOGGLE _"Keep selection" TRUE +) + +(script-fu-menu-register "script-fu-xach-effect" + "<Image>/Filters/Light and Shadow/Shadow") diff --git a/plug-ins/script-fu/tinyscheme/BUILDING b/plug-ins/script-fu/tinyscheme/BUILDING new file mode 100644 index 0000000..5c00236 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/BUILDING @@ -0,0 +1,139 @@ + Building TinyScheme + ------------------- + +The included makefile includes logic for Linux, Solaris and Win32, and can +readily serve as an example for other OSes, especially Unixes. There are +a lot of compile-time flags in TinyScheme (preprocessor defines) that can trim +unwanted features. See next section. 'make all' and 'make clean' function as +expected. + +Autoconfing TinyScheme was once proposed, but the distribution would not be +so small anymore. There are few platform dependencies in TinyScheme, and in +general compiles out of the box. + + Customizing + ----------- + + The following symbols are defined to default values in scheme.h. + Use the -D flag of cc to set to either 1 or 0. + + STANDALONE + Define this to produce a standalone interpreter. + + USE_MATH + Includes math routines. + + USE_CHAR_CLASSIFIERS + Includes character classifier procedures. + + USE_ASCII_NAMES + Enable extended character notation based on ASCII names. + + USE_STRING_PORTS + Enables string ports. + + USE_ERROR_HOOK + To force system errors through user-defined error handling. + (see "Error handling") + + USE_TRACING + To enable use of TRACING. + + USE_COLON_HOOK + Enable use of qualified identifiers. (see "Colon Qualifiers - Packages") + Defining this as 0 has the rather drastic consequence that any code using + packages will stop working, and will have to be modified. It should only + be used if you *absolutely* need to use '::' in identifiers. + + USE_STRCASECMP + Defines stricmp as strcasecmp, for Unix. + + STDIO_ADDS_CR + Informs TinyScheme that stdio translates "\n" to "\r\n". For DOS/Windows. + + USE_DL + Enables dynamically loaded routines. If you define this symbol, you + should also include dynload.c in your compile. + + USE_PLIST + Enables property lists (not Standard Scheme stuff). Off by default. + + USE_NO_FEATURES + Shortcut to disable USE_MATH, USE_CHAR_CLASSIFIERS, USE_ASCII_NAMES, + USE_STRING_PORTS, USE_ERROR_HOOK, USE_TRACING, USE_COLON_HOOK, + USE_DL. + + USE_SCHEME_STACK + Enables 'cons' stack (the alternative is a faster calling scheme, which + breaks continuations). Undefine it if you don't care about strict compatibility + but you do care about faster execution. + + + OS-X tip + -------- + I don't have access to OS-X, but Brian Maher submitted the following tip: + +[1] Download and install fink (I installed fink in +/usr/local/fink) +[2] Install the 'dlcompat' package using fink as such: +> fink install dlcompat +[3] Make the following changes to the +tinyscheme-1.32.tar.gz + +diff -r tinyscheme-1.32/dynload.c +tinyscheme-1.32-new/dynload.c +24c24 +< #define SUN_DL +--- +> +Only in tinyscheme-1.32-new/: dynload.o +Only in tinyscheme-1.32-new/: libtinyscheme.a Only in tinyscheme-1.32-new/: libtinyscheme.so diff -r tinyscheme-1.32/makefile tinyscheme-1.32-new/makefile +33,34c33,43 +< LD = gcc +< LDFLAGS = -shared +--- +> #LD = gcc +> #LDFLAGS = -shared +> #DEBUG=-g -Wno-char-subscripts -O +> #SYS_LIBS= -ldl +> #PLATFORM_FEATURES= -DSUN_DL=1 +> +> # Mac OS X +> CC = gcc +> CFLAGS = -I/usr/local/fink/include +> LD = gcc +> LDFLAGS = -L/usr/local/fink/lib +37c46 +< PLATFORM_FEATURES= -DSUN_DL=1 +--- +> PLATFORM_FEATURES= -DSUN_DL=1 -DOSX +60c69 +< $(CC) -I. -c $(DEBUG) $(FEATURES) +$(DL_FLAGS) $< +--- +> $(CC) $(CFLAGS) -I. -c $(DEBUG) +$(FEATURES) $(DL_FLAGS) $< +66c75 +< $(CC) -o $@ $(DEBUG) $(OBJS) $(SYS_LIBS) +--- +> $(CC) $(LDFLAGS) -o $@ $(DEBUG) $(OBJS) +$(SYS_LIBS) +Only in tinyscheme-1.32-new/: scheme +diff -r tinyscheme-1.32/scheme.c +tinyscheme-1.32-new/scheme.c +60,61c60,61 +< #ifndef macintosh +< # include <malloc.h> +--- +> #ifdef OSX +> /* Do nothing */ +62a63,65 +> # ifndef macintosh +> # include <malloc.h> +> # else +77c80,81 +< #endif /* macintosh */ +--- +> # endif /* macintosh */ +> #endif /* !OSX */ +Only in tinyscheme-1.32-new/: scheme.o diff --git a/plug-ins/script-fu/tinyscheme/CHANGES b/plug-ins/script-fu/tinyscheme/CHANGES new file mode 100644 index 0000000..2f7a33a --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/CHANGES @@ -0,0 +1,326 @@ +Change Log +---------- + +Version 1.41 + Bugs fixed: + #3020389 - Added makefile section for Mac OS X (SL) + #3286135 - Fixed num_mod routine which caused errors in use of modulo + #3290232 - Corrected version number shown on startup (GM) + #3394882 - Added missing #if in opdefines.h around get and put (DC) + #3395547 - Fix for the modulo procedure (DC) + #3400290 - Optimized append to make it an O(n) operation (DC) + #3493926 - Corrected flag used when building shared files on OSX (J) + + R5RS related changes: + #2866196 - Parser does not handle delimiters correctly + #3395548 - Add a decimal point to inexact numbers in atom2str (DC) + #3399331 - Make min/max return inexact when any argument is inexact + #3399332 - Compatibility fix for expt. + #3399335 - Optional radix for string->number and number->string (DC) + #3400202 - Append with one argument should not return a list (DC) + #3400284 - Compatibility fix for integer? + + Other changes: + - Added flags to makefile for MinGW/MSYS (TC) + - Moved variable declarations to avoid warnings with some compilers + - Don't print space after initial #( when printing vectors. + - Minor optimization for is_nonneg(). + - No need to round integers in OP_ROUND (#3400284) + - Fixes to code that reports line number with error (RC) + + Contributors: + Kevin Cozens, Gordon McNutt, Doug Currie, Sean Long, Tim Cas, Joey, + and Richard Copley, and CMarinier. + +Version 1.40 + Bugs fixed: + #1964950 - Stop core dumps due to bad syntax in LET (and variants) + #2826594 - allow reverse to work on empty list (Tony Garnock-Jones) + Potential problem of arglist to foreign calls being wrongly GC'ed. + Fixed bug that read could loop forever (tehom). + + API changes: + Exposed is_list and list_length. + Added scheme_register_foreign_func_list and declarations for it (tehom) + Defined *compile-hook* (tehom) + + Other changes: + Updated is_list and list_length to handle circular lists. + Nested calling thru C has been made now safer (tehom) + Peter Michaux cleaned up port_rep_from_file + Added unwind-protect (tehom) + Some cleanups to in/outport and Eval_Cycle by Peter Michaux + Report error line number (Mostly by Sanel Zukan, back-compatibility by Tehom) + + Contributors: + Kevin Cozens, Dimitrios Souflis, Tom Breton, Peter Michaux, Sanel Zukan, + and Tony Garnock-Jones. + +Version 1.39 + Bugs fixed: + Fix for the load bug + Fixed parsing of octal coded characters. Fixes bug #1818018. + Added tests for when mk_vector is out of memory. Can't rely on sc->sink. + Fix for bug #1794369 + Finished feature-request 1599947: scheme_apply0 etc return values. + Partly provided feature-request 1599947: Expose list_length, eqv, etc + Provided feature-request 1599945, Scheme->C->Scheme calling. + Fix for bug 1593861 (behavior of is_integer) + Fix for bug 1589711 + Error checking of binding spec syntax in LET and LETREC. The bad syntax + was causing a segmentation fault in Linux. Complete fixes for bug #1817986. + Error checking of binding spec syntax in LET* + Bad syntax was causing core dump in Linux. + Fix for nasty gc bug + + R5RS changes: + R5RS requires numbers to be of equal value AND of the same type (ie. both + exact or inexact) in order to return #t from eqv?. R5RS compliance fix. + String output ports now conform to SRFI-6 + + Other changes: + Drew Yao fixed buffer overflow problems in mk_sharp_const. + put OP_T0LVL in charge of reacting to EOF + file_push checks array bounds (patch from Ray Lehtiniemi) + Changed to always use snprintf (Patch due to Ramiro bsd1628) + Updated usage information using text from the Manual.txt file. + +Version 1.38 + Interim release until the rewrite, mostly incorporating modifications + from Kevin Cozens. Small addition for Cygwin in the makefile, and + modifications by Andrew Guenther for Apple platforms. + +Version 1.37 + Joe Buehler submitted reserve_cells. + +Version 1.36 + Joe Buehler fixed a patch in the allocator. + Alexander Shendi moved the comment handling in the scanner, which + fixed an obscure bug for which Mike E had provided a patch as well. + Kevin Cozens has submitted some fixes and modifications which have + not been incorporated yet in their entirety. + +Version 1.35 + Todd Showalter discovered that the number of free cells reported + after GC was incorrect, which could also cause unnecessary allocations. + +Version 1.34 + Long missing version. Lots of bugfixes have accumulated in my email, so + I had to start using them. In this version, Keenan Pepper has submitted + a bugfix for the string comparison library procedure, Wouter Boeke + modified some code that was casting to the wrong type and crashed on + some machines, "SheppardCo" submitted a replacement "modulo" code and + Scott Fenton submitted lots of corrections that shut up some compiler + warnings. Brian Maher submitted instructions on how to build on OS-X. + I have to dig deeper into my mailbox and find earlier emails, too. + +Version 1.33 + Charles Hayden fixed a nasty GC bug of the new stack frame, while in + the process of porting TinyScheme to C++. He also submitted other + changes, and other people also had comments or requests, but the GC + bug was so important that this version is put through the door to + correct it. + +Version 1.32 + Stephen Gildea put some quality time on TinyScheme again, and made + a whole lot of changes to the interpreter that made it noticeably + faster. + +Version 1.31 + Patches to the hastily-done version 1.30. Stephen Gildea fixed + some things done wrongly, and Richard Russo fixed the makefile + for building on Windows. Property lists (heritage from MiniScheme) + are now optional and have disappeared from the interface. They + should be considered as deprecated. + +Version 1.30 + After many months, I followed Preston Bannister's advice of + using macros and a single source text to keep the enums and the + dispatch table in sync, and I used his contributed "opdefines.h". + Timothy Downs contributed a helpful function, "scheme_call". + Stephen Gildea contributed new versions of the makefile and + practically all other sources. He created a built-in STRING-APPEND, + and fixed a lot of other bugs. + Ruhi Bloodworth reported fixes necessary for OS X and a small + bug in dynload.c. + +Version 1.29 + The previous version contained a lot of corrections, but there + were a lot more that still wait on a sheet of paper lost in a + carton someplace after my house move... Manuel Heras-Gilsanz + noticed this and resent his own contribution, which relies on + another bugfix that v.1.28 was missing: a problem with string + output, that this version fixes. I hope other people will take + the time to resend their contributions, if they didn't make it + to v.1.28. + +Version 1.28 + Many people have contacted me with bugfixes or remarks in + the three months I was inactive. A lot of them spotted that + scheme_deinit crashed while reporting gc results. They suggested + that sc->outport be set to NIL in scheme_deinit, which I did. + Dennis Taylor remarked that OP_VALUEPRINT reset sc->value instead + of preserving it. He submitted a modification which I adopted + partially. David Hovemeyer sent me many little changes, that you + will find in version 1.28, and Partice Stoessel modified the + float reader to conform to R5RS. + +Version 1.27 + Version 1.27 is the successor of 1.25. Bug fixes only, but I had to + release them so that everybody can profit. 'Backchar' tried to write + back to the string, which obviously didn't work for const strings. + 'Substring' didn't check for crossed start and end indices. Defines + changed to restore the ability to compile under MSVC. + +Version 1.26 + Version 1.26 was never released. I changed a lot of things, in fact + too much, even the garbage collector, and hell broke loose. I'll + try a more gradual approach next time. + +Version 1.25 + Types have been homogenized to be able to accommodate a different + representation. Plus, promises are no longer closures. Unfortunately, + I discovered that continuations and force/delay do not pass the SCM + test (and never did)... However, on the bright side, what little + modifications I did had a large impact on the footprint: + USE_NO_FEATURES now produces an object file of 63960 bytes on Linux! + +Version 1.24 + SCM tests now pass again after change in atom2str. + +Version 1.23 + Finally I managed to mess it up with my version control. Version + 1.22 actually lacked some of the things I have been fixing in the + meantime. This should be considered as a complete replacement for + 1.22. + +Version 1.22 + The new ports had a bug in LOAD. MK_CLOSURE is introduced. + Shawn Wagner inquired about string->number and number->string. + I added string->atom and atom->string and defined the number + functions from them. Doing that, I fixed WRITE applied to symbols + (it didn't quote them). Unfortunately, minimum build is now + slightly larger than 64k... I postpone action because Jason's idea + might solve it elegantly. + +Version 1.21 + Jason Felice submitted a radically different datatype representation + which he had implemented. While discussing its pros and cons, it + became apparent that the current implementation of ports suffered + from a grave fault: ports were not garbage-collected. I changed the + ports to be heap-allocated, which enabled the use of string ports + for loading. Jason also fixed errors in the garbage collection of + vectors. USE_VERBATIM is gone. "ssp_compiler.c" has a better solution + on HTML generation. A bug involving backslash notation in strings + has been fixed. '-c' flag now executes next argument as a stream of + Scheme commands. Foreign functions are now also heap allocated, + and scheme_define is used to define everything. + +Version 1.20 + Tracing has been added. The toplevel loop has been slightly + rearranged. Backquote reading for vector templates has been + sanitized. Symbol interning is now correct. Arithmetic functions + have been corrected. APPLY, MAP, FOR-EACH, numeric comparison + functions fixed. String reader/writer understands \xAA notation. + +Version 1.19 + Carriage Return now delimits identifiers. DOS-formatted Scheme files + can be used by Unix. Random number generator added to library. + Fixed some glitches of the new type-checking scheme. Fixed erroneous + (append '() 'a) behavior. Will continue with r4rstest.scm to + fix errors. + +Version 1.18 + The FFI has been extended. USE_VERBOSE_GC has gone. Anyone wanting + the same functionality can put (gcverbose #t) in init.scm. + print-width was removed, along with three corresponding op-codes. + Extended character constants with ASCII names were added. + mk_counted_string paves the way for full support of binary strings. + As much as possible of the type-checking chores were delegated + to the inner loop, thus reducing the code size to less than 4200 loc! + +Version 1.17 + Dynamically-loaded extensions are more fully integrated. + TinyScheme is now distributed under the BSD open-source license. + +Version 1.16 + Dynamically-loaded extensions introduced (USE_DL). + Santeri Paavolainen found a race condition: When a cons is executed, + and each of the two arguments is a constructing function, GC could + happen before all arguments are evaluated and cons() is called, and + the evaluated arguments would all be reclaimed! + Fortunately, such a case was rare in the code, although it is + a pitfall in new code and code in foreign functions. Currently, only + one such case remains, when COLON_HOOK is defined. + +Version 1.15 + David Gould also contributed some changes that speed up operation. + Kirk Zurell fixed HASPROP. + The Garbage Collection didn't collect all the garbage...fixed. + +Version 1.14 + Unfortunately, after Andre fixed the GC it became obvious that the + algorithm was too slow... Fortunately, David Gould found a way to + speed it up. + +Version 1.13 + Silly bug involving division by zero resolved by Roland Kaufman. + Macintoch support from Shmulik Regev. + Float parser bug fixed by Alexander Shendi. + GC bug from Andru Luvisi. + +Version 1.12 + Cis* incorrectly called isalpha() instead of isascii() + Added USE_CHAR_CLASSIFIERS, USE_STRING_PORTS. + +Version 1.11 + BSDI defines isnumber... changed all similar functions to is_* + EXPT now has correct definition. Added FLOOR,CEILING,TRUNCATE + and ROUND, courtesy of Bengt Kleberg. Preprocessor symbols now + have values 1 or 0, and can be set as compiler defines (proposed + by Andy Ganor *months* ago). 'prompt' and 'InitFile' can now be + defined during compilation, too. + +Version 1.10 + Another bug when file ends with comment! + Added DEFINE-MACRO in init.scm, courtesy of Andy Gaynor. + +Version 1.09 + Removed bug when READ met EOF. lcm. + +Version 1.08 + quotient,remainder and modulo. gcd. + +Version 1.07 + '=>' in cond now exists + list? now checks for circularity + some reader bugs removed + Reader is more consistent wrt vectors + Quote and Quasiquote work with vectors + +Version 1.06 + #! is now skipped + generic-assoc bug removed + strings are now managed differently, hack.txt is removed + various delicate points fixed + +Version 1.05 + Support for scripts, *args*, "-1" option. + Various R5RS procedures. + *sharp-hook* + Handles unmatched parentheses. + New architecture for procedures. + +Version 1.04 + Added missing T_ATOM bits... + Added vectors + Free-list is sorted by address, since vectors need consecutive cells. + (quit <exitcode>) for use with scripts + +Version 1.03 (26 Aug 1998): + Extended .h with useful functions for FFI + Library: with-input-* etc. + Finished R5RS I/O, added string ports. + +Version 1.02 (25 Aug 1998): + First part of R5RS I/O. diff --git a/plug-ins/script-fu/tinyscheme/COPYING b/plug-ins/script-fu/tinyscheme/COPYING new file mode 100644 index 0000000..a6c49a2 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/COPYING @@ -0,0 +1,31 @@ + LICENSE TERMS + +Copyright (c) 2000, Dimitrios Souflis +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Dimitrios Souflis nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/plug-ins/script-fu/tinyscheme/Makefile.am b/plug-ins/script-fu/tinyscheme/Makefile.am new file mode 100644 index 0000000..49ce643 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/Makefile.am @@ -0,0 +1,26 @@ +## Process this file with automake to produce Makefile.in + +AM_CFLAGS = \ + -DSTANDALONE=0 \ + -DUSE_INTERFACE=1 \ + -DUSE_MATH=1 \ + -DUSE_ASCII_NAMES=0 \ + -DUSE_STRLWR=0 \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) + +noinst_LIBRARIES = libtinyscheme.a + +libtinyscheme_a_SOURCES = \ + scheme.c \ + opdefines.h \ + scheme-private.h \ + scheme.h + +EXTRA_DIST = \ + BUILDING \ + CHANGES \ + COPYING \ + hack.txt \ + Manual.txt \ + MiniSCHEMETribute.txt diff --git a/plug-ins/script-fu/tinyscheme/Makefile.in b/plug-ins/script-fu/tinyscheme/Makefile.in new file mode 100644 index 0000000..c506dfe --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/Makefile.in @@ -0,0 +1,924 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = plug-ins/script-fu/tinyscheme +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libtinyscheme_a_AR = $(AR) $(ARFLAGS) +libtinyscheme_a_LIBADD = +am_libtinyscheme_a_OBJECTS = scheme.$(OBJEXT) +libtinyscheme_a_OBJECTS = $(am_libtinyscheme_a_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/scheme.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtinyscheme_a_SOURCES) +DIST_SOURCES = $(libtinyscheme_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING \ + README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = \ + -DSTANDALONE=0 \ + -DUSE_INTERFACE=1 \ + -DUSE_MATH=1 \ + -DUSE_ASCII_NAMES=0 \ + -DUSE_STRLWR=0 \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) + +noinst_LIBRARIES = libtinyscheme.a +libtinyscheme_a_SOURCES = \ + scheme.c \ + opdefines.h \ + scheme-private.h \ + scheme.h + +EXTRA_DIST = \ + BUILDING \ + CHANGES \ + COPYING \ + hack.txt \ + Manual.txt \ + MiniSCHEMETribute.txt + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plug-ins/script-fu/tinyscheme/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plug-ins/script-fu/tinyscheme/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libtinyscheme.a: $(libtinyscheme_a_OBJECTS) $(libtinyscheme_a_DEPENDENCIES) $(EXTRA_libtinyscheme_a_DEPENDENCIES) + $(AM_V_at)-rm -f libtinyscheme.a + $(AM_V_AR)$(libtinyscheme_a_AR) libtinyscheme.a $(libtinyscheme_a_OBJECTS) $(libtinyscheme_a_LIBADD) + $(AM_V_at)$(RANLIB) libtinyscheme.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheme.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/scheme.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/scheme.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir 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 maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/plug-ins/script-fu/tinyscheme/Manual.txt b/plug-ins/script-fu/tinyscheme/Manual.txt new file mode 100644 index 0000000..7ef62e9 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/Manual.txt @@ -0,0 +1,452 @@ + + + TinySCHEME Version 1.41 + + "Safe if used as prescribed" + -- Philip K. Dick, "Ubik" + +This software is open source, covered by a BSD-style license. +Please read accompanying file COPYING. +------------------------------------------------------------------------------- + + This Scheme interpreter is based on MiniSCHEME version 0.85k4 + (see miniscm.tar.gz in the Scheme Repository) + Original credits in file MiniSCHEMETribute.txt. + + D. Souflis (dsouflis@acm.org) + +------------------------------------------------------------------------------- + What is TinyScheme? + ------------------- + + TinyScheme is a lightweight Scheme interpreter that implements as large + a subset of R5RS as was possible without getting very large and + complicated. It is meant to be used as an embedded scripting interpreter + for other programs. As such, it does not offer IDEs or extensive toolkits + although it does sport a small top-level loop, included conditionally. + A lot of functionality in TinyScheme is included conditionally, to allow + developers freedom in balancing features and footprint. + + As an embedded interpreter, it allows multiple interpreter states to + coexist in the same program, without any interference between them. + Programmatically, foreign functions in C can be added and values + can be defined in the Scheme environment. Being a quite small program, + it is easy to comprehend, get to grips with, and use. + + Known bugs + ---------- + + TinyScheme is known to misbehave when memory is exhausted. + + + Things that keep missing, or that need fixing + --------------------------------------------- + + There are no hygienic macros. No rational or + complex numbers. No unwind-protect and call-with-values. + + Maybe (a subset of) SLIB will work with TinySCHEME... + + Decent debugging facilities are missing. Only tracing is supported + natively. + + + Scheme Reference + ---------------- + + If something seems to be missing, please refer to the code and + "init.scm", since some are library functions. Refer to the MiniSCHEME + readme as a last resort. + + Environments + (interaction-environment) + See R5RS. In TinySCHEME, immutable list of association lists. + + (current-environment) + The environment in effect at the time of the call. An example of its + use and its utility can be found in the sample code that implements + packages in "init.scm": + + (macro (package form) + `(apply (lambda () + ,@(cdr form) + (current-environment)))) + + The environment containing the (local) definitions inside the closure + is returned as an immutable value. + + (defined? <symbol>) (defined? <symbol> <environment>) + Checks whether the given symbol is defined in the current (or given) + environment. + + Symbols + (gensym) + Returns a new interned symbol each time. Will probably move to the + library when string->symbol is implemented. + + Directives + (gc) + Performs garbage collection immediately. + + (gcverbose) (gcverbose <bool>) + The argument (defaulting to #t) controls whether GC produces + visible outcome. + + (quit) (quit <num>) + Stops the interpreter and sets the 'retcode' internal field (defaults + to 0). When standalone, 'retcode' is returned as exit code to the OS. + + (tracing <num>) + 1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1). + + Mathematical functions + Since rationals and complexes are absent, the respective functions + are also missing. + Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling, + trunc, round and also sqrt and expt when USE_MATH=1. + Number-theoretical quotient, remainder and modulo, gcd, lcm. + Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?, + exact->inexact. inexact->exact is a core function. + + Type predicates + boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?, + char?,port?,input-port?,output-port?,procedure?,pair?,environment?', + vector?. Also closure?, macro?. + + Types + Types supported: + + Numbers (integers and reals) + Symbols + Pairs + Strings + Characters + Ports + Eof object + Environments + Vectors + + Literals + String literals can contain escaped quotes \" as usual, but also + \n, \r, \t, \xDD (hex representations) and \DDD (octal representations). + Note also that it is possible to include literal newlines in string + literals, e.g. + + (define s "String with newline here + and here + that can function like a HERE-string") + + Character literals contain #\space and #\newline and are supplemented + with #\return and #\tab, with obvious meanings. Hex character + representations are allowed (e.g. #\x20 is #\space). + When USE_ASCII_NAMES is defined, various control characters can be + referred to by their ASCII name. + 0 #\nul 17 #\dc1 + 1 #\soh 18 #\dc2 + 2 #\stx 19 #\dc3 + 3 #\etx 20 #\dc4 + 4 #\eot 21 #\nak + 5 #\enq 22 #\syn + 6 #\ack 23 #\etv + 7 #\bel 24 #\can + 8 #\bs 25 #\em + 9 #\ht 26 #\sub + 10 #\lf 27 #\esc + 11 #\vt 28 #\fs + 12 #\ff 29 #\gs + 13 #\cr 30 #\rs + 14 #\so 31 #\us + 15 #\si + 16 #\dle 127 #\del + + Numeric literals support #x #o #b and #d. Flonums are currently read only + in decimal notation. Full grammar will be supported soon. + + Quote, quasiquote etc. + As usual. + + Immutable values + Immutable pairs cannot be modified by set-car! and set-cdr!. + Immutable strings cannot be modified via string-set! + + I/O + As per R5RS, plus String Ports (see below). + current-input-port, current-output-port, + close-input-port, close-output-port, input-port?, output-port?, + open-input-file, open-output-file. + read, write, display, newline, write-char, read-char, peek-char. + char-ready? returns #t only for string ports, because there is no + portable way in stdio to determine if a character is available. + Also open-input-output-file, set-input-port, set-output-port (not R5RS) + Library: call-with-input-file, call-with-output-file, + with-input-from-file, with-output-from-file and + with-input-output-from-to-files, close-port and input-output-port? + (not R5RS). + String Ports: open-input-string, open-output-string, get-output-string, + open-input-output-string. Strings can be used with I/O routines. + + Vectors + make-vector, vector, vector-length, vector-ref, vector-set!, list->vector, + vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS) + + Strings + string, make-string, list->string, string-length, string-ref, string-set!, + substring, string->list, string-fill!, string-append, string-copy. + string=?, string<?, string>?, string>?, string<=?, string>=?. + (No string-ci*? yet). string->number, number->string. Also atom->string, + string->atom (not R5RS). + + Symbols + symbol->string, string->symbol + + Characters + integer->char, char->integer. + char=?, char<?, char>?, char<=?, char>=?. + (No char-ci*?) + + Pairs & Lists + cons, car, cdr, list, length, map, for-each, foldr, list-tail, + list-ref, last-pair, reverse, append. + Also member, memq, memv, based on generic-member, assoc, assq, assv + based on generic-assoc. + + Streams + head, tail, cons-stream + + Control features + Apart from procedure?, also macro? and closure? + map, for-each, force, delay, call-with-current-continuation (or call/cc), + eval, apply. 'Forcing' a value that is not a promise produces the value. + There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in + the presence of continuations would require support from the abstract + machine itself. + + Property lists + TinyScheme inherited from MiniScheme property lists for symbols. + put, get. + + Dynamically-loaded extensions + (load-extension <filename without extension>) + Loads a DLL declaring foreign procedures. On Unix/Linux, one can make use + of the ld.so.conf file or the LD_RUN_PATH system variable in order to place + the library in a directory other than the current one. Please refer to the + appropriate 'man' page. + + Esoteric procedures + (oblist) + Returns the oblist, an immutable list of all the symbols. + + (macro-expand <form>) + Returns the expanded form of the macro call denoted by the argument + + (define-with-return (<procname> <args>...) <body>) + Like plain 'define', but makes the continuation available as 'return' + inside the procedure. Handy for imperative programs. + + (new-segment <num>) + Allocates more memory segments. + + defined? + See "Environments" + + (get-closure-code <closure>) + Gets the code as scheme data. + + (make-closure <code> <environment>) + Makes a new closure in the given environment. + + Obsolete procedures + (print-width <object>) + + Programmer's Reference + ---------------------- + + The interpreter state is initialized with "scheme_init". + Custom memory allocation routines can be installed with an alternate + initialization function: "scheme_init_custom_alloc". + Files can be loaded with "scheme_load_file". Strings containing Scheme + code can be loaded with "scheme_load_string". It is a good idea to + "scheme_load" init.scm before anything else. + + External data for keeping external state (of use to foreign functions) + can be installed with "scheme_set_external_data". + Foreign functions are installed with "assign_foreign". Additional + definitions can be added to the interpreter state, with "scheme_define" + (this is the way HTTP header data and HTML form data are passed to the + Scheme script in the Altera SQL Server). If you wish to define the + foreign function in a specific environment (to enhance modularity), + use "assign_foreign_env". + + The procedure "scheme_apply0" has been added with persistent scripts in + mind. Persistent scripts are loaded once, and every time they are needed + to produce HTTP output, appropriate data are passed through global + definitions and function "main" is called to do the job. One could + add easily "scheme_apply1" etc. + + The interpreter state should be deinitialized with "scheme_deinit". + + DLLs containing foreign functions should define a function named + init_<base-name>. E.g. foo.dll should define init_foo, and bar.so + should define init_bar. This function should assign_foreign any foreign + function contained in the DLL. + + The first dynamically loaded extension available for TinyScheme is + a regular expression library. Although it's by no means an + established standard, this library is supposed to be installed in + a directory mirroring its name under the TinyScheme location. + + + Foreign Functions + ----------------- + + The user can add foreign functions in C. For example, a function + that squares its argument: + + pointer square(scheme *sc, pointer args) { + if(args!=sc->NIL) { + if(sc->isnumber(sc->pair_car(args))) { + double v=sc->rvalue(sc->pair_car(args)); + return sc->mk_real(sc,v*v); + } + } + return sc->NIL; + } + + Foreign functions are now defined as closures: + + sc->interface->scheme_define( + sc, + sc->global_env, + sc->interface->mk_symbol(sc,"square"), + sc->interface->mk_foreign_func(sc, square)); + + + Foreign functions can use the external data in the "scheme" struct + to implement any kind of external state. + + External data are set with the following function: + void scheme_set_external_data(scheme *sc, void *p); + + As of v.1.17, the canonical way for a foreign function in a DLL to + manipulate Scheme data is using the function pointers in sc->interface. + + Standalone + ---------- + + Usage: tinyscheme -? + or: tinyscheme [<file1> <file2> ...] + followed by + -1 <file> [<arg1> <arg2> ...] + -c <Scheme commands> [<arg1> <arg2> ...] + assuming that the executable is named tinyscheme. + + Use - in the place of a filename to denote stdin. + The -1 flag is meant for #! usage in shell scripts. If you specify + #! /somewhere/tinyscheme -1 + then tinyscheme will be called to process the file. For example, the + following script echoes the Scheme list of its arguments. + + #! /somewhere/tinyscheme -1 + (display *args*) + + The -c flag permits execution of arbitrary Scheme code. + + + Error Handling + -------------- + + Errors are recovered from without damage. The user can install his + own handler for system errors, by defining *error-hook*. Defining + to '() gives the default behavior, which is equivalent to "error". + USE_ERROR_HOOK must be defined. + + A simple exception handling mechanism can be found in "init.scm". + A new syntactic form is introduced: + + (catch <expr returned exceptionally> + <expr1> <expr2> ... <exprN>) + + "Catch" establishes a scope spanning multiple call-frames + until another "catch" is encountered. + + Exceptions are thrown with: + + (throw "message") + + If used outside a (catch ...), reverts to (error "message"). + + Example of use: + + (define (foo x) (write x) (newline) (/ x 0)) + + (catch (begin (display "Error!\n") 0) + (write "Before foo ... ") + (foo 5) + (write "After foo")) + + The exception mechanism can be used even by system errors, by + + (define *error-hook* throw) + + which makes use of the error hook described above. + + If necessary, the user can devise his own exception mechanism with + tagged exceptions etc. + + + Reader extensions + ----------------- + + When encountering an unknown character after '#', the user-specified + procedure *sharp-hook* (if any), is called to read the expression. + This can be used to extend the reader to handle user-defined constants + or whatever. It should be a procedure without arguments, reading from + the current input port (which will be the load-port). + + + Colon Qualifiers - Packages + --------------------------- + + When USE_COLON_HOOK=1: + The lexer now recognizes the construction <qualifier>::<symbol> and + transforms it in the following manner (T is the transformation function): + + T(<qualifier>::<symbol>) = (*colon-hook* 'T(<symbol>) <qualifier>) + + where <qualifier> is a symbol not containing any double-colons. + + As the definition is recursive, qualifiers can be nested. + The user can define his own *colon-hook*, to handle qualified names. + By default, "init.scm" defines *colon-hook* as EVAL. Consequently, + the qualifier must denote a Scheme environment, such as one returned + by (interaction-environment). "Init.scm" defines a new syntantic form, + PACKAGE, as a simple example. It is used like this: + + (define toto + (package + (define foo 1) + (define bar +))) + + foo ==> Error, "foo" undefined + (eval 'foo) ==> Error, "foo" undefined + (eval 'foo toto) ==> 1 + toto::foo ==> 1 + ((eval 'bar toto) 2 (eval 'foo toto)) ==> 3 + (toto::bar 2 toto::foo) ==> 3 + (eval (bar 2 foo) toto) ==> 3 + + If the user installs another package infrastructure, he must define + a new 'package' procedure or macro to retain compatibility with supplied + code. + + Note: Older versions used ':' as a qualifier. Unfortunately, the use + of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially + precludes its use as a real qualifier. + + + + + + + + diff --git a/plug-ins/script-fu/tinyscheme/MiniSCHEMETribute.txt b/plug-ins/script-fu/tinyscheme/MiniSCHEMETribute.txt new file mode 100644 index 0000000..185f0ec --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/MiniSCHEMETribute.txt @@ -0,0 +1,88 @@ + TinyScheme would not exist if it wasn't for MiniScheme. I had just + written the HTTP server for Ovrimos SQL Server, and I was lamenting the + lack of a scripting language. Server-side Javascript would have been the + preferred solution, had there been a Javascript interpreter I could + lay my hands on. But there weren't. Perl would have been another solution, + but it was probably ten times bigger that the program it was supposed to + be embedded in. There would also be thorny licencing issues. + + So, the obvious thing to do was find a truly small interpreter. Forth + was a language I had once quasi-implemented, but the difficulty of + handling dynamic data and the weirdness of the language put me off. I then + looked around for a LISP interpreter, the next thing I knew was easy to + implement. Alas, the LeLisp I knew from my days in UPMC (Universite Pierre + et Marie Curie) had given way to Common Lisp, a megalith of a language! + Then my search lead me to Scheme, a language I knew was very orthogonal + and clean. When I found Mini-Scheme, a single C file of some 2400 loc, I + fell in love with it! What if it lacked floating-point numbers and + strings! The rest, as they say, is history. + + Below are the original credits. Don't email Akira KIDA, the address has + changed. + + ---------- Mini-Scheme Interpreter Version 0.85 ---------- + + coded by Atsushi Moriwaki (11/5/1989) + + E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp + + THIS SOFTWARE IS IN THE PUBLIC DOMAIN + ------------------------------------ + This software is completely free to copy, modify and/or re-distribute. + But I would appreciate it if you left my name on the code as the author. + + This version has been modified by R.C. Secrist. + + Mini-Scheme is now maintained by Akira KIDA. + + This is a revised and modified version by Akira KIDA. + current version is 0.85k4 (15 May 1994) + + Please send suggestions, bug reports and/or requests to: + <SDI00379@niftyserve.or.jp> + + + Features compared to MiniSCHEME + ------------------------------- + + All code is now reentrant. Interpreter state is held in a 'scheme' + struct, and many interpreters can coexist in the same program, possibly + in different threads. The user can specify user-defined memory allocation + primitives. (see "Programmer's Reference") + + The reader is more consistent. + + Strings, characters and flonums are supported. (see "Types") + + Files being loaded can be nested up to some depth. + + R5RS I/O is there, plus String Ports. (see "Scheme Reference","I/O") + + Vectors exist. + + As a standalone application, it supports command-line arguments. + (see "Standalone") + + Running out of memory is now handled. + + The user can add foreign functions in C. (see "Foreign Functions") + + The code has been changed slightly, core functions have been moved + to the library, behavior has been aligned with R5RS etc. + + Support has been added for user-defined error recovery. + (see "Error Handling") + + Support has been added for modular programming. + (see "Colon Qualifiers - Packages") + + To enable this, EVAL has changed internally, and can + now take two arguments, as per R5RS. Environments are supported. + (see "Colon Qualifiers - Packages") + + Promises are now evaluated once only. + + (macro (foo form) ...) is now equivalent to (macro foo (lambda(form) ...)) + + The reader can be extended using new #-expressions + (see "Reader extensions") diff --git a/plug-ins/script-fu/tinyscheme/README b/plug-ins/script-fu/tinyscheme/README new file mode 100644 index 0000000..4411119 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/README @@ -0,0 +1,14 @@ +This directory contains a version of TinyScheme which has been modified +to support UTF-8 coded strings. The strings stored in a data cell are +expected to be in UTF-8 format. This allows the continued use of gchar +pointers to pass around the strings. Processing the strings will require +conversion to unicode at times depending on the specific operation that +needs to be done on the UTF-8 coded strings. + +The string length value stored in a data cell is the length in bytes of that +string including the terminating NUL. + +Routines that want a string length for a UTF-8 coded string will be passed +the number of characters and not the number of bytes. If the number of bytes +is needed, the normal call to strlen() will work. + diff --git a/plug-ins/script-fu/tinyscheme/hack.txt b/plug-ins/script-fu/tinyscheme/hack.txt new file mode 100644 index 0000000..6aba7a7 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/hack.txt @@ -0,0 +1,233 @@ + + How to hack TinyScheme + ---------------------- + + TinyScheme is easy to learn and modify. It is structured like a + meta-interpreter, only it is written in C. All data are Scheme + objects, which facilitates both understanding/modifying the + code and reifying the interpreter workings. + + In place of a dry description, we will pace through the addition + of a useful new datatype: garbage-collected memory blocks. + The interface will be: + + (make-block <n> [<fill>]) makes a new block of the specified size + optionally filling it with a specified byte + (block? <obj>) + (block-length <block>) + (block-ref <block> <index>) retrieves byte at location + (block-set! <block> <index> <byte>) modifies byte at location + + In the sequel, lines that begin with '>' denote lines to add to the + code. Lines that begin with '|' are just citations of existing code. + Lines that begin with X are deleted. + + First of all, we need to assign a typeid to our new type. Typeids + in TinyScheme are small integers declared in an enum, very close to + the top of scheme.c; it begins with T_STRING. Add a new one before the + end, call it T_MEMBLOCK. Adjust T_LAST_SYSTEM_TYPE. + +| T_ENVIRONMENT=14, +X T_LAST_SYSTEM_TYPE=14 +> T_MEMBLOCK=15, +> T_LAST_SYSTEM_TYPE=15 +| }; + + Then, some helper macros would be useful. Go to where is_string() and + the rest are defined and define: + +> int is_memblock(pointer p) { return (type(p)==T_MEMBLOCK); } + + This actually is a function, because it is meant to be exported by + scheme.h. If no foreign function will ever manipulate a memory block, + you can instead define it as a macro + +> #define is_memblock(p) (type(p)==T_MEMBLOCK) + + Then we make space for the new type in the main data structure: + struct cell. As it happens, the _string part of the union _object + (that is used to hold character strings) has two fields that suit us: + +| struct { +| char *_svalue; +| int _keynum; +| } _string; + + We can use _svalue to hold the actual pointer and _keynum to hold its + length. If we couldn't reuse existing fields, we could always add other + alternatives in union _object. + + We then proceed to write the function that actually makes a new block. + For conformance reasons, we name it mk_memblock + +> static pointer mk_memblock(scheme *sc, int len, char fill) { +> pointer x; +> char *p=(char*)sc->malloc(len); +> +> if(p==0) { +> return sc->NIL; +> } +> x = get_cell(sc, sc->NIL, sc->NIL); +> +> typeflag(x) = T_MEMBLOCK|T_ATOM; +> strvalue(x)=p; +> keynum(x)=len; +> memset(p,fill,len); +> return (x); +> } + + The memory used by the MEMBLOCK will have to be freed when the cell + is reclaimed during garbage collection. There is a placeholder for + that staff, function finalize_cell(), currently handling strings only. + +| static void finalize_cell(scheme *sc, pointer a) { +| if(is_string(a)) { +| sc->free(strvalue(a)); +> else if(is_memblock(a)) { +> sc->free(strvalue(a)); +| } else if(is_port(a)) { + + There are no MEMBLOCK literals, so we don't concern ourselves with + the READER part (yet!). We must cater to the PRINTER, though. We + add one case more in atom2str(). + +| } else if (is_foreign(l)) { +| p = sc->strbuff; +| snprintf(p,STRBUFFSIZE,"#<FOREIGN PROCEDURE %ld>", procnum(l)); +> } else if (ismemblock(l)) { +> p = "#<MEMBLOCK>"; +| } else if (is_continuation(l)) { +| p = "#<CONTINUATION>"; +| } else { + + Whenever a MEMBLOCK is displayed, it will look like that. + + Now, we must add the interface functions: constructor, predicate, + accessor, modifier. We must in fact create new op-codes for the + virtual machine underlying TinyScheme. Since version 1.30, TinyScheme + uses macros and a single source text to keep the enums and the + dispatch table in sync. That's where the op-codes are declared. Note + that the opdefines.h file uses unusually long lines to accommodate + all the information; adjust your editor to handle this. The file has + six columns: A to Z. they contain: + - Column A is the name of a routine to handle the scheme function. + - Column B is the name the scheme function. + - Columns C and D are the minimum and maximum number of arguments + that are accepted by the scheme function. + - Column E is a set of flags that are used when the interpreter + verifies that the passed parameters are of the correct type. + - Column F is used to create a set of enums. The enum is used in a + switch in the routine listed in column A to get to the code that + does the work needed for the scheme function. + For reasons of cohesion, we add the new op-codes right after those + for vectors: + +| _OP_DEF(opexe_2, "vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET ) +> _OP_DEF(opexe_2, "make-block", 1, 2, TST_NATURAL TST_CHAR, OP_MKBLOCK ) +> _OP_DEF(opexe_2, "block-length", 1, 1, T_MEMBLOCK, OP_BLOCKLEN ) +> _OP_DEF(opexe_2, "block-ref", 2, 2, T_MEMBLOCK TST_NATURAL, OP_BLOCKREF ) +> _OP_DEF(opexe_2, "block-set!", 1, 1, T_MEMBLOCK TST_NATURAL TST_CHAR, OP_BLOCKSET ) +| _OP_DEF(opexe_3, "not", 1, 1, TST_NONE, OP_NOT ) + + We add the predicate along the other predicates: + +| _OP_DEF(opexe_3, "vector?", 1, 1, TST_ANY, OP_VECTORP ) +> _OP_DEF(opexe_3, "block?", 1, 1, TST_ANY, OP_BLOCKP ) +| _OP_DEF(opexe_3, "eq?", 2, 2, TST_ANY, OP_EQ ) + + All that remains is to write the actual processing in opexe_2, right + after OP_VECSET. + +> case OP_MKBLOCK: { /* make-block */ +> int fill=0; +> int len; +> +> if(!isnumber(car(sc->args))) { +> Error_1(sc,"make-block: not a number:",car(sc->args)); +> } +> len=ivalue(car(sc->args)); +> if(len<=0) { +> Error_1(sc,"make-block: not positive:",car(sc->args)); +> } +> +> if(cdr(sc->args)!=sc->NIL) { +> if(!isnumber(cadr(sc->args)) || ivalue(cadr(sc->args))<0) { +> Error_1(sc,"make-block: not a positive number:",cadr(sc->args)); +> } +> fill=charvalue(cadr(sc->args))%255; +> } +> s_return(sc,mk_memblock(sc,len,(char)fill)); +> } +> +> case OP_BLOCKLEN: /* block-length */ +> if(!ismemblock(car(sc->args))) { +> Error_1(sc,"block-length: not a memory block:",car(sc->args)); +> } +> s_return(sc,mk_integer(sc,keynum(car(sc->args)))); +> +> case OP_BLOCKREF: { /* block-ref */ +> char *str; +> int index; +> +> if(!ismemblock(car(sc->args))) { +> Error_1(sc,"block-ref: not a memory block:",car(sc->args)); +> } +> str=strvalue(car(sc->args)); +> +> if(cdr(sc->args)==sc->NIL) { +> Error_0(sc,"block-ref: needs two arguments"); +> } +> if(!isnumber(cadr(sc->args))) { +> Error_1(sc,"block-ref: not a number:",cadr(sc->args)); +> } +> index=ivalue(cadr(sc->args)); +> +> if(index<0 || index>=keynum(car(sc->args))) { +> Error_1(sc,"block-ref: out of bounds:",cadr(sc->args)); +> } +> +> s_return(sc,mk_integer(sc,str[index])); +> } +> +> case OP_BLOCKSET: { /* block-set! */ +> char *str; +> int index; +> int c; +> +> if(!ismemblock(car(sc->args))) { +> Error_1(sc,"block-set!: not a memory block:",car(sc->args)); +> } +> if(isimmutable(car(sc->args))) { +> Error_1(sc,"block-set!: unable to alter immutable memory block:",car(sc->args)); +> } +> str=strvalue(car(sc->args)); +> +> if(cdr(sc->args)==sc->NIL) { +> Error_0(sc,"block-set!: needs three arguments"); +> } +> if(!isnumber(cadr(sc->args))) { +> Error_1(sc,"block-set!: not a number:",cadr(sc->args)); +> } +> index=ivalue(cadr(sc->args)); +> if(index<0 || index>=keynum(car(sc->args))) { +> Error_1(sc,"block-set!: out of bounds:",cadr(sc->args)); +> } +> +> if(cddr(sc->args)==sc->NIL) { +> Error_0(sc,"block-set!: needs three arguments"); +> } +> if(!isinteger(caddr(sc->args))) { +> Error_1(sc,"block-set!: not an integer:",caddr(sc->args)); +> } +> c=ivalue(caddr(sc->args))%255; +> +> str[index]=(char)c; +> s_return(sc,car(sc->args)); +> } + + Same for the predicate in opexe_3. + +| case OP_VECTORP: /* vector? */ +| s_retbool(isvector(car(sc->args))); +> case OP_BLOCKP: /* block? */ +> s_retbool(ismemblock(car(sc->args))); diff --git a/plug-ins/script-fu/tinyscheme/opdefines.h b/plug-ins/script-fu/tinyscheme/opdefines.h new file mode 100644 index 0000000..ceb4d0e --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/opdefines.h @@ -0,0 +1,195 @@ + _OP_DEF(opexe_0, "load", 1, 1, TST_STRING, OP_LOAD ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_T0LVL ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_T1LVL ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_READ_INTERNAL ) + _OP_DEF(opexe_0, "gensym", 0, 0, 0, OP_GENSYM ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_VALUEPRINT ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_EVAL ) +#if USE_TRACING + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_REAL_EVAL ) +#endif + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_E0ARGS ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_E1ARGS ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_APPLY ) +#if USE_TRACING + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_REAL_APPLY ) + _OP_DEF(opexe_0, "tracing", 1, 1, TST_NATURAL, OP_TRACING ) +#endif + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DOMACRO ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LAMBDA ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LAMBDA1 ) + _OP_DEF(opexe_0, "make-closure", 1, 2, TST_PAIR TST_ENVIRONMENT, OP_MKCLOSURE ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_QUOTE ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DEF0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DEF1 ) + _OP_DEF(opexe_0, "defined?", 1, 2, TST_SYMBOL TST_ENVIRONMENT, OP_DEFP ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_BEGIN ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_IF0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_IF1 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_SET0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_SET1 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET1 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET2 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET0AST ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET1AST ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET2AST ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET0REC ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET1REC ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET2REC ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_COND0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_COND1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_DELAY ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_AND0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_AND1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_OR0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_OR1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_C0STREAM ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_C1STREAM ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_MACRO0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_MACRO1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE2 ) + _OP_DEF(opexe_1, "eval", 1, 2, TST_ANY TST_ENVIRONMENT, OP_PEVAL ) + _OP_DEF(opexe_1, "apply", 1, INF_ARG, TST_NONE, OP_PAPPLY ) + _OP_DEF(opexe_1, "call-with-current-continuation", 1, 1, TST_NONE, OP_CONTINUATION ) +#if USE_MATH + _OP_DEF(opexe_2, "inexact->exact", 1, 1, TST_NUMBER, OP_INEX2EX ) + _OP_DEF(opexe_2, "exp", 1, 1, TST_NUMBER, OP_EXP ) + _OP_DEF(opexe_2, "log", 1, 1, TST_NUMBER, OP_LOG ) + _OP_DEF(opexe_2, "sin", 1, 1, TST_NUMBER, OP_SIN ) + _OP_DEF(opexe_2, "cos", 1, 1, TST_NUMBER, OP_COS ) + _OP_DEF(opexe_2, "tan", 1, 1, TST_NUMBER, OP_TAN ) + _OP_DEF(opexe_2, "asin", 1, 1, TST_NUMBER, OP_ASIN ) + _OP_DEF(opexe_2, "acos", 1, 1, TST_NUMBER, OP_ACOS ) + _OP_DEF(opexe_2, "atan", 1, 2, TST_NUMBER, OP_ATAN ) + _OP_DEF(opexe_2, "sqrt", 1, 1, TST_NUMBER, OP_SQRT ) + _OP_DEF(opexe_2, "expt", 2, 2, TST_NUMBER, OP_EXPT ) + _OP_DEF(opexe_2, "floor", 1, 1, TST_NUMBER, OP_FLOOR ) + _OP_DEF(opexe_2, "ceiling", 1, 1, TST_NUMBER, OP_CEILING ) + _OP_DEF(opexe_2, "truncate", 1, 1, TST_NUMBER, OP_TRUNCATE ) + _OP_DEF(opexe_2, "round", 1, 1, TST_NUMBER, OP_ROUND ) +#endif + _OP_DEF(opexe_2, "+", 0, INF_ARG, TST_NUMBER, OP_ADD ) + _OP_DEF(opexe_2, "-", 1, INF_ARG, TST_NUMBER, OP_SUB ) + _OP_DEF(opexe_2, "*", 0, INF_ARG, TST_NUMBER, OP_MUL ) + _OP_DEF(opexe_2, "/", 1, INF_ARG, TST_NUMBER, OP_DIV ) + _OP_DEF(opexe_2, "quotient", 1, INF_ARG, TST_INTEGER, OP_INTDIV ) + _OP_DEF(opexe_2, "remainder", 2, 2, TST_INTEGER, OP_REM ) + _OP_DEF(opexe_2, "modulo", 2, 2, TST_INTEGER, OP_MOD ) + _OP_DEF(opexe_2, "car", 1, 1, TST_PAIR, OP_CAR ) + _OP_DEF(opexe_2, "cdr", 1, 1, TST_PAIR, OP_CDR ) + _OP_DEF(opexe_2, "cons", 2, 2, TST_NONE, OP_CONS ) + _OP_DEF(opexe_2, "set-car!", 2, 2, TST_PAIR TST_ANY, OP_SETCAR ) + _OP_DEF(opexe_2, "set-cdr!", 2, 2, TST_PAIR TST_ANY, OP_SETCDR ) + _OP_DEF(opexe_2, "char->integer", 1, 1, TST_CHAR, OP_CHAR2INT ) + _OP_DEF(opexe_2, "integer->char", 1, 1, TST_NATURAL, OP_INT2CHAR ) + _OP_DEF(opexe_2, "char-upcase", 1, 1, TST_CHAR, OP_CHARUPCASE ) + _OP_DEF(opexe_2, "char-downcase", 1, 1, TST_CHAR, OP_CHARDNCASE ) + _OP_DEF(opexe_2, "symbol->string", 1, 1, TST_SYMBOL, OP_SYM2STR ) + _OP_DEF(opexe_2, "atom->string", 1, 2, TST_ANY TST_NATURAL, OP_ATOM2STR ) + _OP_DEF(opexe_2, "string->symbol", 1, 1, TST_STRING, OP_STR2SYM ) + _OP_DEF(opexe_2, "string->atom", 1, 2, TST_STRING TST_NATURAL, OP_STR2ATOM ) + _OP_DEF(opexe_2, "make-string", 1, 2, TST_NATURAL TST_CHAR, OP_MKSTRING ) + _OP_DEF(opexe_2, "string-length", 1, 1, TST_STRING, OP_STRLEN ) + _OP_DEF(opexe_2, "string-ref", 2, 2, TST_STRING TST_NATURAL, OP_STRREF ) + _OP_DEF(opexe_2, "string-set!", 3, 3, TST_STRING TST_NATURAL TST_CHAR, OP_STRSET ) + _OP_DEF(opexe_2, "string-append", 0, INF_ARG, TST_STRING, OP_STRAPPEND ) + _OP_DEF(opexe_2, "substring", 2, 3, TST_STRING TST_NATURAL, OP_SUBSTR ) + _OP_DEF(opexe_2, "vector", 0, INF_ARG, TST_NONE, OP_VECTOR ) + _OP_DEF(opexe_2, "make-vector", 1, 2, TST_NATURAL TST_ANY, OP_MKVECTOR ) + _OP_DEF(opexe_2, "vector-length", 1, 1, TST_VECTOR, OP_VECLEN ) + _OP_DEF(opexe_2, "vector-ref", 2, 2, TST_VECTOR TST_NATURAL, OP_VECREF ) + _OP_DEF(opexe_2, "vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET ) + _OP_DEF(opexe_3, "not", 1, 1, TST_NONE, OP_NOT ) + _OP_DEF(opexe_3, "boolean?", 1, 1, TST_NONE, OP_BOOLP ) + _OP_DEF(opexe_3, "eof-object?", 1, 1, TST_NONE, OP_EOFOBJP ) + _OP_DEF(opexe_3, "null?", 1, 1, TST_NONE, OP_NULLP ) + _OP_DEF(opexe_3, "=", 2, INF_ARG, TST_NUMBER, OP_NUMEQ ) + _OP_DEF(opexe_3, "<", 2, INF_ARG, TST_NUMBER, OP_LESS ) + _OP_DEF(opexe_3, ">", 2, INF_ARG, TST_NUMBER, OP_GRE ) + _OP_DEF(opexe_3, "<=", 2, INF_ARG, TST_NUMBER, OP_LEQ ) + _OP_DEF(opexe_3, ">=", 2, INF_ARG, TST_NUMBER, OP_GEQ ) + _OP_DEF(opexe_3, "symbol?", 1, 1, TST_ANY, OP_SYMBOLP ) + _OP_DEF(opexe_3, "number?", 1, 1, TST_ANY, OP_NUMBERP ) + _OP_DEF(opexe_3, "string?", 1, 1, TST_ANY, OP_STRINGP ) + _OP_DEF(opexe_3, "integer?", 1, 1, TST_ANY, OP_INTEGERP ) + _OP_DEF(opexe_3, "real?", 1, 1, TST_ANY, OP_REALP ) + _OP_DEF(opexe_3, "char?", 1, 1, TST_ANY, OP_CHARP ) +#if USE_CHAR_CLASSIFIERS + _OP_DEF(opexe_3, "char-alphabetic?", 1, 1, TST_CHAR, OP_CHARAP ) + _OP_DEF(opexe_3, "char-numeric?", 1, 1, TST_CHAR, OP_CHARNP ) + _OP_DEF(opexe_3, "char-whitespace?", 1, 1, TST_CHAR, OP_CHARWP ) + _OP_DEF(opexe_3, "char-upper-case?", 1, 1, TST_CHAR, OP_CHARUP ) + _OP_DEF(opexe_3, "char-lower-case?", 1, 1, TST_CHAR, OP_CHARLP ) +#endif + _OP_DEF(opexe_3, "port?", 1, 1, TST_ANY, OP_PORTP ) + _OP_DEF(opexe_3, "input-port?", 1, 1, TST_ANY, OP_INPORTP ) + _OP_DEF(opexe_3, "output-port?", 1, 1, TST_ANY, OP_OUTPORTP ) + _OP_DEF(opexe_3, "procedure?", 1, 1, TST_ANY, OP_PROCP ) + _OP_DEF(opexe_3, "pair?", 1, 1, TST_ANY, OP_PAIRP ) + _OP_DEF(opexe_3, "list?", 1, 1, TST_ANY, OP_LISTP ) + _OP_DEF(opexe_3, "environment?", 1, 1, TST_ANY, OP_ENVP ) + _OP_DEF(opexe_3, "vector?", 1, 1, TST_ANY, OP_VECTORP ) + _OP_DEF(opexe_3, "eq?", 2, 2, TST_ANY, OP_EQ ) + _OP_DEF(opexe_3, "eqv?", 2, 2, TST_ANY, OP_EQV ) + _OP_DEF(opexe_4, "force", 1, 1, TST_ANY, OP_FORCE ) + _OP_DEF(opexe_4, 0, 0, 0, 0, OP_SAVE_FORCED ) + _OP_DEF(opexe_4, "write", 1, 2, TST_ANY TST_OUTPORT, OP_WRITE ) + _OP_DEF(opexe_4, "write-char", 1, 2, TST_CHAR TST_OUTPORT, OP_WRITE_CHAR ) + _OP_DEF(opexe_4, "display", 1, 2, TST_ANY TST_OUTPORT, OP_DISPLAY ) + _OP_DEF(opexe_4, "newline", 0, 1, TST_OUTPORT, OP_NEWLINE ) + _OP_DEF(opexe_4, "error", 1, INF_ARG, TST_NONE, OP_ERR0 ) + _OP_DEF(opexe_4, 0, 0, 0, 0, OP_ERR1 ) + _OP_DEF(opexe_4, "reverse", 1, 1, TST_LIST, OP_REVERSE ) + _OP_DEF(opexe_4, "list*", 1, INF_ARG, TST_NONE, OP_LIST_STAR ) + _OP_DEF(opexe_4, "append", 0, INF_ARG, TST_NONE, OP_APPEND ) +#if USE_PLIST + _OP_DEF(opexe_4, "put", 3, 3, TST_NONE, OP_PUT ) + _OP_DEF(opexe_4, "get", 2, 2, TST_NONE, OP_GET ) +#endif + _OP_DEF(opexe_4, "quit", 0, 1, TST_NUMBER, OP_QUIT ) + _OP_DEF(opexe_4, "gc", 0, 0, 0, OP_GC ) + _OP_DEF(opexe_4, "gc-verbose", 0, 1, TST_NONE, OP_GCVERB ) + _OP_DEF(opexe_4, "new-segment", 0, 1, TST_NUMBER, OP_NEWSEGMENT ) + _OP_DEF(opexe_4, "oblist", 0, 0, 0, OP_OBLIST ) + _OP_DEF(opexe_4, "current-input-port", 0, 0, 0, OP_CURR_INPORT ) + _OP_DEF(opexe_4, "current-output-port", 0, 0, 0, OP_CURR_OUTPORT ) + _OP_DEF(opexe_4, "open-input-file", 1, 1, TST_STRING, OP_OPEN_INFILE ) + _OP_DEF(opexe_4, "open-output-file", 1, 1, TST_STRING, OP_OPEN_OUTFILE ) + _OP_DEF(opexe_4, "open-input-output-file", 1, 1, TST_STRING, OP_OPEN_INOUTFILE ) +#if USE_STRING_PORTS + _OP_DEF(opexe_4, "open-input-string", 1, 1, TST_STRING, OP_OPEN_INSTRING ) + _OP_DEF(opexe_4, "open-input-output-string", 1, 1, TST_STRING, OP_OPEN_INOUTSTRING ) + _OP_DEF(opexe_4, "open-output-string", 0, 1, TST_STRING, OP_OPEN_OUTSTRING ) + _OP_DEF(opexe_4, "get-output-string", 1, 1, TST_OUTPORT, OP_GET_OUTSTRING ) +#endif + _OP_DEF(opexe_4, "close-input-port", 1, 1, TST_INPORT, OP_CLOSE_INPORT ) + _OP_DEF(opexe_4, "close-output-port", 1, 1, TST_OUTPORT, OP_CLOSE_OUTPORT ) + _OP_DEF(opexe_4, "interaction-environment", 0, 0, 0, OP_INT_ENV ) + _OP_DEF(opexe_4, "current-environment", 0, 0, 0, OP_CURR_ENV ) + _OP_DEF(opexe_5, "read", 0, 1, TST_INPORT, OP_READ ) + _OP_DEF(opexe_5, "read-char", 0, 1, TST_INPORT, OP_READ_CHAR ) + _OP_DEF(opexe_5, "peek-char", 0, 1, TST_INPORT, OP_PEEK_CHAR ) + _OP_DEF(opexe_5, "char-ready?", 0, 1, TST_INPORT, OP_CHAR_READY ) + _OP_DEF(opexe_5, "set-input-port", 1, 1, TST_INPORT, OP_SET_INPORT ) + _OP_DEF(opexe_5, "set-output-port", 1, 1, TST_OUTPORT, OP_SET_OUTPORT ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDSEXPR ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDLIST ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDDOT ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQUOTE ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQQUOTE ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQQUOTEVEC ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDUNQUOTE ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDUQTSP ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDVEC ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_P0LIST ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_P1LIST ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_PVECFROM ) + _OP_DEF(opexe_6, "length", 1, 1, TST_LIST, OP_LIST_LENGTH ) + _OP_DEF(opexe_6, "assq", 2, 2, TST_NONE, OP_ASSQ ) + _OP_DEF(opexe_6, "get-closure-code", 1, 1, TST_NONE, OP_GET_CLOSURE ) + _OP_DEF(opexe_6, "closure?", 1, 1, TST_NONE, OP_CLOSUREP ) + _OP_DEF(opexe_6, "macro?", 1, 1, TST_NONE, OP_MACROP ) +#undef _OP_DEF diff --git a/plug-ins/script-fu/tinyscheme/scheme-private.h b/plug-ins/script-fu/tinyscheme/scheme-private.h new file mode 100644 index 0000000..89840c2 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/scheme-private.h @@ -0,0 +1,227 @@ +/* scheme-private.h */ + +#ifndef _SCHEME_PRIVATE_H +#define _SCHEME_PRIVATE_H + +#include "scheme.h" +/*------------------ Ugly internals -----------------------------------*/ +/*------------------ Of interest only to FFI users --------------------*/ + +enum scheme_port_kind { + port_free=0, + port_file=1, + port_string=2, + port_srfi6=4, + port_input=16, + port_output=32, + port_saw_EOF=64 +}; + +typedef struct port { + unsigned char kind; + union { + struct { + FILE *file; + int closeit; +#if SHOW_ERROR_LINE + int curr_line; + char *filename; +#endif + } stdio; + struct { + char *start; + char *past_the_end; + char *curr; + } string; + } rep; +} port; + +/* cell structure */ +struct cell { + unsigned int _flag; + union { + struct { + char *_svalue; + int _length; + } _string; + num _number; + port *_port; + foreign_func _ff; + struct { + struct cell *_car; + struct cell *_cdr; + } _cons; + } _object; +}; + +struct scheme { +/* arrays for segments */ +func_alloc malloc; +func_dealloc free; + +/* return code */ +int retcode; +int tracing; + + +#ifndef CELL_SEGSIZE +#define CELL_SEGSIZE 25000 /* # of cells in one segment */ +#endif +#ifndef CELL_NSEGMENT +#define CELL_NSEGMENT 50 /* # of segments for cells */ +#endif +char *alloc_seg[CELL_NSEGMENT]; +pointer cell_seg[CELL_NSEGMENT]; +int last_cell_seg; + +/* We use 5 registers. */ +pointer args; /* register for arguments of function */ +pointer envir; /* stack register for current environment */ +pointer code; /* register for current code */ +pointer dump; /* stack register for next evaluation */ +pointer foreign_error; /* used for foreign functions to signal an error */ + +int interactive_repl; /* are we in an interactive REPL? */ +int print_output; /* set to 1 to print results and error messages */ + +struct cell _sink; +pointer sink; /* when mem. alloc. fails */ +struct cell _NIL; +pointer NIL; /* special cell representing empty cell */ +struct cell _HASHT; +pointer T; /* special cell representing #t */ +struct cell _HASHF; +pointer F; /* special cell representing #f */ +struct cell _EOF_OBJ; +pointer EOF_OBJ; /* special cell representing end-of-file object */ +pointer oblist; /* pointer to symbol table */ +pointer global_env; /* pointer to global environment */ + +pointer c_nest; /* stack for nested calls from C */ + +/* global pointers to special symbols */ +pointer LAMBDA; /* pointer to syntax lambda */ +pointer QUOTE; /* pointer to syntax quote */ + +pointer QQUOTE; /* pointer to symbol quasiquote */ +pointer UNQUOTE; /* pointer to symbol unquote */ +pointer UNQUOTESP; /* pointer to symbol unquote-splicing */ +pointer FEED_TO; /* => */ +pointer COLON_HOOK; /* *colon-hook* */ +pointer ERROR_HOOK; /* *error-hook* */ +pointer SHARP_HOOK; /* *sharp-hook* */ +pointer COMPILE_HOOK; /* *compile-hook* */ + +pointer free_cell; /* pointer to top of free cells */ +long fcells; /* # of free cells */ + +pointer inport; +pointer outport; +pointer save_inport; +pointer loadport; + +#ifndef MAXFIL +#define MAXFIL 64 +#endif +port load_stack[MAXFIL]; /* Stack of open files for port -1 (LOADing) */ +int nesting_stack[MAXFIL]; +int file_i; +int nesting; + +char gc_verbose; /* if gc_verbose is not zero, print gc status */ +char no_memory; /* Whether mem. alloc. has failed */ + +#ifndef LINESIZE +#define LINESIZE 1024 +#endif +char linebuff[LINESIZE]; +#ifndef STRBUFFSIZE +#define STRBUFFSIZE 1024 +#endif +char strbuff[STRBUFFSIZE]; + +FILE *tmpfp; +int tok; +int print_flag; +pointer value; +int op; + +void *ext_data; /* For the benefit of foreign functions */ +long gensym_cnt; + +struct scheme_interface *vptr; +void *dump_base; /* pointer to base of allocated dump stack */ +int dump_size; /* number of frames allocated for dump stack */ + +gunichar backchar[2]; +int bc_flag; +}; + +/* operator code */ +enum scheme_opcodes { +#define _OP_DEF(A,B,C,D,E,OP) OP, +#include "opdefines.h" + OP_MAXDEFINED +}; + +#ifdef __cplusplus +extern "C" { +#endif + +#define cons(sc,a,b) _cons(sc,a,b,0) +#define immutable_cons(sc,a,b) _cons(sc,a,b,1) + +int is_string(pointer p); +char *string_value(pointer p); +int is_number(pointer p); +num nvalue(pointer p); +long ivalue(pointer p); +double rvalue(pointer p); +int is_integer(pointer p); +int is_real(pointer p); +int is_character(pointer p); +int string_length(pointer p); +gunichar charvalue(pointer p); +int is_vector(pointer p); + +int is_port(pointer p); +int is_inport(pointer p); +int is_outport(pointer p); + +int is_pair(pointer p); +pointer pair_car(pointer p); +pointer pair_cdr(pointer p); +pointer set_car(pointer p, pointer q); +pointer set_cdr(pointer p, pointer q); + +int is_symbol(pointer p); +char *symname(pointer p); +char *symkey(pointer p); +int hasprop(pointer p); + +int is_syntax(pointer p); +int is_proc(pointer p); +int is_foreign(pointer p); +char *syntaxname(pointer p); +int is_closure(pointer p); +int is_macro(pointer p); +pointer closure_code(pointer p); +pointer closure_env(pointer p); + +int is_continuation(pointer p); +int is_promise(pointer p); +int is_environment(pointer p); +int is_immutable(pointer p); +void setimmutable(pointer p); + +#ifdef __cplusplus +} +#endif + +#endif + +/* +Local variables: +c-file-style: "k&r" +End: +*/ diff --git a/plug-ins/script-fu/tinyscheme/scheme.c b/plug-ins/script-fu/tinyscheme/scheme.c new file mode 100644 index 0000000..ff73801 --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/scheme.c @@ -0,0 +1,5352 @@ +/* T I N Y S C H E M E 1 . 4 1 + * Dimitrios Souflis (dsouflis@acm.org) + * Based on MiniScheme (original credits follow) + * (MINISCM) coded by Atsushi Moriwaki (11/5/1989) + * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp + * (MINISCM) This version has been modified by R.C. Secrist. + * (MINISCM) + * (MINISCM) Mini-Scheme is now maintained by Akira KIDA. + * (MINISCM) + * (MINISCM) This is a revised and modified version by Akira KIDA. + * (MINISCM) current version is 0.85k4 (15 May 1994) + * + */ + +/* ******** READ THE FOLLOWING BEFORE MODIFYING THIS FILE! ******** */ +/* This copy of TinyScheme has been modified to support UTF-8 coded */ +/* character strings. As a result, the length of a string in bytes */ +/* may not be the same as the length of a string in characters. You */ +/* must keep this in mind at all times while making any changes to */ +/* the routines in this file and when adding new features. */ +/* */ +/* UTF-8 modifications made by Kevin Cozens (kcozens@interlog.com) */ +/* **************************************************************** */ + +#include "config.h" + +#define _SCHEME_SOURCE +#if HAVE_UNISTD_H +# include <unistd.h> +#endif +#if USE_DL +# include "dynload.h" +#endif +#if USE_MATH +# include <math.h> +#endif + +#include <limits.h> +#include <float.h> +#include <ctype.h> +#include <stdint.h> +#include <string.h> + +#include "../script-fu-intl.h" + +#include "scheme-private.h" + +#if !STANDALONE +static ts_output_func ts_output_handler = NULL; +static gpointer ts_output_data = NULL; + +void +ts_register_output_func (ts_output_func func, + gpointer user_data) +{ + ts_output_handler = func; + ts_output_data = user_data; +} + +/* len is length of 'string' in bytes or -1 for null terminated strings */ +void +ts_output_string (TsOutputType type, + const char *string, + int len) +{ + if (len < 0) + len = strlen (string); + + if (ts_output_handler && len > 0) + (* ts_output_handler) (type, string, len, ts_output_data); +} +#endif + +/* Used for documentation purposes, to signal functions in 'interface' */ +#define INTERFACE + +#define TOK_EOF (-1) +#define TOK_LPAREN 0 +#define TOK_RPAREN 1 +#define TOK_DOT 2 +#define TOK_ATOM 3 +#define TOK_QUOTE 4 +#define TOK_COMMENT 5 +#define TOK_DQUOTE 6 +#define TOK_BQUOTE 7 +#define TOK_COMMA 8 +#define TOK_ATMARK 9 +#define TOK_SHARP 10 +#define TOK_SHARP_CONST 11 +#define TOK_VEC 12 +#define TOK_USCORE 13 + +#define BACKQUOTE '`' +#define DELIMITERS "()\";\f\t\v\n\r " + +/* + * Basic memory allocation units + */ + +#define banner "TinyScheme 1.41 (with UTF-8 support)" + +#include <string.h> +#include <stdlib.h> + +#define stricmp utf8_stricmp + +static int utf8_stricmp(const char *s1, const char *s2) +{ + char *s1a, *s2a; + int result; + + s1a = g_utf8_casefold(s1, -1); + s2a = g_utf8_casefold(s2, -1); + + result = g_utf8_collate(s1a, s2a); + + g_free(s1a); + g_free(s2a); + return result; +} + +#define min(a, b) ((a) <= (b) ? (a) : (b)) + +#if USE_STRLWR +/* +#error FIXME: Can't just use g_utf8_strdown since it allocates a new string +#define strlwr(s) g_utf8_strdown(s, -1) +*/ +#else +#define strlwr(s) s +#endif + +#ifndef prompt +# define prompt "ts> " +#endif + +#ifndef InitFile +# define InitFile "init.scm" +#endif + +#ifndef FIRST_CELLSEGS +# define FIRST_CELLSEGS 3 +#endif + +enum scheme_types { + T_STRING=1, + T_NUMBER=2, + T_SYMBOL=3, + T_PROC=4, + T_PAIR=5, + T_CLOSURE=6, + T_CONTINUATION=7, + T_FOREIGN=8, + T_CHARACTER=9, + T_PORT=10, + T_VECTOR=11, + T_MACRO=12, + T_PROMISE=13, + T_ENVIRONMENT=14, + T_LAST_SYSTEM_TYPE=14 +}; + +/* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */ +#define ADJ 32 +#define TYPE_BITS 5 +#define T_MASKTYPE 31 /* 0000000000011111 */ +#define T_SYNTAX 4096 /* 0001000000000000 */ +#define T_IMMUTABLE 8192 /* 0010000000000000 */ +#define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */ +#define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */ +#define MARK 32768 /* 1000000000000000 */ +#define UNMARK 32767 /* 0111111111111111 */ + +static num num_add(num a, num b); +static num num_mul(num a, num b); +static num num_div(num a, num b); +static num num_intdiv(num a, num b); +static num num_sub(num a, num b); +static num num_rem(num a, num b); +static num num_mod(num a, num b); +static int num_eq(num a, num b); +static int num_gt(num a, num b); +static int num_ge(num a, num b); +static int num_lt(num a, num b); +static int num_le(num a, num b); + +#if USE_MATH +static double round_per_R5RS(double x); +#endif +static int is_zero_double(double x); +static INLINE int num_is_integer(pointer p) { + return ((p)->_object._number.is_fixnum); +} + +static num num_zero; +static num num_one; + +/* macros for cell operations */ +#define typeflag(p) ((p)->_flag) +#define type(p) (typeflag(p)&T_MASKTYPE) + +INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); } +#define strvalue(p) ((p)->_object._string._svalue) +#define strlength(p) ((p)->_object._string._length) + +INTERFACE static int is_list(scheme *sc, pointer a); +INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); } +INTERFACE static void fill_vector(pointer vec, pointer obj); +INTERFACE static pointer vector_elem(pointer vec, int ielem); +INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a); +INTERFACE INLINE int is_number(pointer p) { return (type(p)==T_NUMBER); } +INTERFACE INLINE int is_integer(pointer p) { + if (!is_number(p)) + return 0; + if (num_is_integer(p) || (double)ivalue(p) == rvalue(p)) + return 1; + return 0; +} + +INTERFACE INLINE int is_real(pointer p) { + return is_number(p) && (!(p)->_object._number.is_fixnum); +} + +INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); } +INTERFACE INLINE int string_length(pointer p) { return strlength(p); } +INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); } +INLINE num nvalue(pointer p) { return ((p)->_object._number); } +INTERFACE long ivalue(pointer p) { return (num_is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); } +INTERFACE double rvalue(pointer p) { return (!num_is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); } +#define ivalue_unchecked(p) ((p)->_object._number.value.ivalue) +#define rvalue_unchecked(p) ((p)->_object._number.value.rvalue) +#define set_num_integer(p) (p)->_object._number.is_fixnum=1; +#define set_num_real(p) (p)->_object._number.is_fixnum=0; +INTERFACE gunichar charvalue(pointer p) { return (gunichar)ivalue_unchecked(p); } + +INTERFACE INLINE int is_port(pointer p) { return (type(p)==T_PORT); } +INTERFACE INLINE int is_inport(pointer p) { return is_port(p) && p->_object._port->kind & port_input; } +INTERFACE INLINE int is_outport(pointer p) { return is_port(p) && p->_object._port->kind & port_output; } + +INTERFACE INLINE int is_pair(pointer p) { return (type(p)==T_PAIR); } +#define car(p) ((p)->_object._cons._car) +#define cdr(p) ((p)->_object._cons._cdr) +INTERFACE pointer pair_car(pointer p) { return car(p); } +INTERFACE pointer pair_cdr(pointer p) { return cdr(p); } +INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; } +INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; } + +INTERFACE INLINE int is_symbol(pointer p) { return (type(p)==T_SYMBOL); } +INTERFACE INLINE char *symname(pointer p) { return strvalue(car(p)); } +#if USE_PLIST +SCHEME_EXPORT INLINE int hasprop(pointer p) { return (typeflag(p)&T_SYMBOL); } +#define symprop(p) cdr(p) +#endif + +INTERFACE INLINE int is_syntax(pointer p) { return (typeflag(p)&T_SYNTAX); } +INTERFACE INLINE int is_proc(pointer p) { return (type(p)==T_PROC); } +INTERFACE INLINE int is_foreign(pointer p) { return (type(p)==T_FOREIGN); } +INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); } +#define procnum(p) ivalue(p) +static const char *procname(pointer x); + +INTERFACE INLINE int is_closure(pointer p) { return (type(p)==T_CLOSURE); } +INTERFACE INLINE int is_macro(pointer p) { return (type(p)==T_MACRO); } +INTERFACE INLINE pointer closure_code(pointer p) { return car(p); } +INTERFACE INLINE pointer closure_env(pointer p) { return cdr(p); } + +INTERFACE INLINE int is_continuation(pointer p) { return (type(p)==T_CONTINUATION); } +#define cont_dump(p) cdr(p) + +/* To do: promise should be forced ONCE only */ +INTERFACE INLINE int is_promise(pointer p) { return (type(p)==T_PROMISE); } + +INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); } +#define setenvironment(p) typeflag(p) = T_ENVIRONMENT + +#define is_atom(p) (typeflag(p)&T_ATOM) +#define setatom(p) typeflag(p) |= T_ATOM +#define clratom(p) typeflag(p) &= CLRATOM + +#define is_mark(p) (typeflag(p)&MARK) +#define setmark(p) typeflag(p) |= MARK +#define clrmark(p) typeflag(p) &= UNMARK + +INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); } +/*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/ +INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; } + +#define caar(p) car(car(p)) +#define cadr(p) car(cdr(p)) +#define cdar(p) cdr(car(p)) +#define cddr(p) cdr(cdr(p)) +#define cadar(p) car(cdr(car(p))) +#define caddr(p) car(cdr(cdr(p))) +#define cdaar(p) cdr(car(car(p))) +#define cadaar(p) car(cdr(car(car(p)))) +#define cadddr(p) car(cdr(cdr(cdr(p)))) +#define cddddr(p) cdr(cdr(cdr(cdr(p)))) + +#if USE_CHAR_CLASSIFIERS +static INLINE int Cisalpha(gunichar c) { return g_unichar_isalpha(c); } +static INLINE int Cisdigit(gunichar c) { return g_unichar_isdigit(c); } +static INLINE int Cisspace(gunichar c) { return g_unichar_isspace(c); } +static INLINE int Cisupper(gunichar c) { return g_unichar_isupper(c); } +static INLINE int Cislower(gunichar c) { return g_unichar_islower(c); } +#endif + +#if USE_ASCII_NAMES +static const char *charnames[32]={ + "nul", + "soh", + "stx", + "etx", + "eot", + "enq", + "ack", + "bel", + "bs", + "ht", + "lf", + "vt", + "ff", + "cr", + "so", + "si", + "dle", + "dc1", + "dc2", + "dc3", + "dc4", + "nak", + "syn", + "etb", + "can", + "em", + "sub", + "esc", + "fs", + "gs", + "rs", + "us" +}; + +static int is_ascii_name(const char *name, int *pc) { + int i; + for(i=0; i<32; i++) { + if(stricmp(name,charnames[i])==0) { + *pc=i; + return 1; + } + } + if(stricmp(name,"del")==0) { + *pc=127; + return 1; + } + return 0; +} + +#endif + +/* Number of bytes expected AFTER lead byte of UTF-8 character. */ +static const char utf8_length[64] = +{ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */ + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */ + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,0,0 /* 0xf0-0xff */ +}; + +static int file_push(scheme *sc, const char *fname); +static void file_pop(scheme *sc); +static int file_interactive(scheme *sc); +static INLINE int is_one_of(char *s, gunichar c); +static int alloc_cellseg(scheme *sc, int n); +static long binary_decode(const char *s); +static INLINE pointer get_cell(scheme *sc, pointer a, pointer b); +static pointer _get_cell(scheme *sc, pointer a, pointer b); +static pointer reserve_cells(scheme *sc, int n); +static pointer get_consecutive_cells(scheme *sc, int n); +static pointer find_consecutive_cells(scheme *sc, int n); +static void finalize_cell(scheme *sc, pointer a); +static int count_consecutive_cells(pointer x, int needed); +static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all); +static pointer mk_number(scheme *sc, num n); +static char *store_string(scheme *sc, int len, const char *str, gunichar fill); +static pointer mk_vector(scheme *sc, int len); +static pointer mk_atom(scheme *sc, char *q); +static pointer mk_sharp_const(scheme *sc, char *name); +static pointer mk_port(scheme *sc, port *p); +static pointer port_from_filename(scheme *sc, const char *fn, int prop); +static pointer port_from_file(scheme *sc, FILE *, int prop); +static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop); +static port *port_rep_from_filename(scheme *sc, const char *fn, int prop); +static port *port_rep_from_file(scheme *sc, FILE *, int prop); +static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop); +static void port_close(scheme *sc, pointer p, int flag); +static void mark(pointer a); +static void gc(scheme *sc, pointer a, pointer b); +static gunichar basic_inchar(port *pt); +static gunichar inchar(scheme *sc); +static void backchar(scheme *sc, gunichar c); +static char *readstr_upto(scheme *sc, char *delim); +static pointer readstrexp(scheme *sc); +static INLINE int skipspace(scheme *sc); +static int token(scheme *sc); +static void printslashstring(scheme *sc, char *s, int len); +static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen); +static void printatom(scheme *sc, pointer l, int f); +static pointer mk_proc(scheme *sc, enum scheme_opcodes op); +static pointer mk_closure(scheme *sc, pointer c, pointer e); +static pointer mk_continuation(scheme *sc, pointer d); +static pointer reverse(scheme *sc, pointer a); +static pointer reverse_in_place(scheme *sc, pointer term, pointer list); +static pointer revappend(scheme *sc, pointer a, pointer b); +int list_length(scheme *sc, pointer a); +int eqv(pointer a, pointer b); + +static INLINE void dump_stack_mark(scheme *); +static pointer opexe_0(scheme *sc, enum scheme_opcodes op); +static pointer opexe_1(scheme *sc, enum scheme_opcodes op); +static pointer opexe_2(scheme *sc, enum scheme_opcodes op); +static pointer opexe_3(scheme *sc, enum scheme_opcodes op); +static pointer opexe_4(scheme *sc, enum scheme_opcodes op); +static pointer opexe_5(scheme *sc, enum scheme_opcodes op); +static pointer opexe_6(scheme *sc, enum scheme_opcodes op); +static void Eval_Cycle(scheme *sc, enum scheme_opcodes op); +static void assign_syntax(scheme *sc, char *name); +static int syntaxnum(pointer p); +static void assign_proc(scheme *sc, enum scheme_opcodes, char *name); +scheme *scheme_init_new(void); + +#define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue) +#define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue) + +static num num_add(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue+b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)+num_rvalue(b); + } + return ret; +} + +static num num_mul(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue*b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)*num_rvalue(b); + } + return ret; +} + +static num num_div(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue/b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)/num_rvalue(b); + } + return ret; +} + +static num num_intdiv(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue/b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)/num_rvalue(b); + } + return ret; +} + +static num num_sub(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue-b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)-num_rvalue(b); + } + return ret; +} + +static num num_rem(num a, num b) { + num ret; + long e1, e2, res; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + e1=num_ivalue(a); + e2=num_ivalue(b); + res=e1%e2; + /* remainder should have same sign as first operand */ + if (res > 0) { + if (e1 < 0) { + res -= labs(e2); + } + } else if (res < 0) { + if (e1 > 0) { + res += labs(e2); + } + } + ret.value.ivalue=res; + return ret; +} + +static num num_mod(num a, num b) { + num ret; + long e1, e2, res; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + e1=num_ivalue(a); + e2=num_ivalue(b); + res=e1%e2; + /* modulo should have same sign as second operand */ + if ((res < 0) != (e2 < 0) && res) { /* if their sign is different... */ + res+=e2; + } + ret.value.ivalue=res; + return ret; +} + +static int num_eq(num a, num b) { + int ret; + int is_fixnum=a.is_fixnum && b.is_fixnum; + if(is_fixnum) { + ret= a.value.ivalue==b.value.ivalue; + } else { + ret=num_rvalue(a)==num_rvalue(b); + } + return ret; +} + + +static int num_gt(num a, num b) { + int ret; + int is_fixnum=a.is_fixnum && b.is_fixnum; + if(is_fixnum) { + ret= a.value.ivalue>b.value.ivalue; + } else { + ret=num_rvalue(a)>num_rvalue(b); + } + return ret; +} + +static int num_ge(num a, num b) { + return !num_lt(a,b); +} + +static int num_lt(num a, num b) { + int ret; + int is_fixnum=a.is_fixnum && b.is_fixnum; + if(is_fixnum) { + ret= a.value.ivalue<b.value.ivalue; + } else { + ret=num_rvalue(a)<num_rvalue(b); + } + return ret; +} + +static int num_le(num a, num b) { + return !num_gt(a,b); +} + +#if USE_MATH +/* Round to nearest. Round to even if midway */ +static double round_per_R5RS(double x) { + double fl=floor(x); + double ce=ceil(x); + double dfl=x-fl; + double dce=ce-x; + if(dfl>dce) { + return ce; + } else if(dfl<dce) { + return fl; + } else { + if(fmod(fl,2.0)==0.0) { /* I imagine this holds */ + return fl; + } else { + return ce; + } + } +} +#endif + +static int is_zero_double(double x) { + return x<DBL_MIN && x>-DBL_MIN; +} + +static long binary_decode(const char *s) { + long x=0; + + while(*s!=0 && (*s=='1' || *s=='0')) { + x<<=1; + x+=*s-'0'; + s++; + } + + return x; +} + +/* allocate new cell segment */ +static int alloc_cellseg(scheme *sc, int n) { + pointer newp; + pointer last; + pointer p; + char *cp; + long i; + int k; + int adj=ADJ; + + if(adj<sizeof(struct cell)) { + adj=sizeof(struct cell); + } + + for (k = 0; k < n; k++) { + if (sc->last_cell_seg >= CELL_NSEGMENT - 1) + return k; + cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj); + if (cp == 0) + return k; + i = ++sc->last_cell_seg ; + sc->alloc_seg[i] = cp; + /* adjust in TYPE_BITS-bit boundary */ + if(((uintptr_t)cp)%adj!=0) { + cp=(char*)(adj*((uintptr_t)cp/adj+1)); + } + /* insert new segment in address order */ + newp=(pointer)cp; + sc->cell_seg[i] = newp; + while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) { + p = sc->cell_seg[i]; + sc->cell_seg[i] = sc->cell_seg[i - 1]; + sc->cell_seg[--i] = p; + } + sc->fcells += CELL_SEGSIZE; + last = newp + CELL_SEGSIZE - 1; + for (p = newp; p <= last; p++) { + typeflag(p) = 0; + cdr(p) = p + 1; + car(p) = sc->NIL; + } + /* insert new cells in address order on free list */ + if (sc->free_cell == sc->NIL || p < sc->free_cell) { + cdr(last) = sc->free_cell; + sc->free_cell = newp; + } else { + p = sc->free_cell; + while (cdr(p) != sc->NIL && newp > cdr(p)) + p = cdr(p); + cdr(last) = cdr(p); + cdr(p) = newp; + } + } + return n; +} + +static INLINE pointer get_cell_x(scheme *sc, pointer a, pointer b) { + if (sc->free_cell != sc->NIL) { + pointer x = sc->free_cell; + sc->free_cell = cdr(x); + --sc->fcells; + return (x); + } + return _get_cell (sc, a, b); +} + + +/* get new cell. parameter a, b is marked by gc. */ +static pointer _get_cell(scheme *sc, pointer a, pointer b) { + pointer x; + + if(sc->no_memory) { + return sc->sink; + } + + if (sc->free_cell == sc->NIL) { + const int min_to_be_recovered = sc->last_cell_seg*8; + gc(sc,a, b); + if (sc->fcells < min_to_be_recovered + || sc->free_cell == sc->NIL) { + /* if only a few recovered, get more to avoid fruitless gc's */ + if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) { + sc->no_memory=1; + return sc->sink; + } + } + } + x = sc->free_cell; + sc->free_cell = cdr(x); + --sc->fcells; + return (x); +} + +/* make sure that there is a given number of cells free */ +static pointer reserve_cells(scheme *sc, int n) { + if(sc->no_memory) { + return sc->NIL; + } + + /* Are there enough cells available? */ + if (sc->fcells < n) { + /* If not, try gc'ing some */ + gc(sc, sc->NIL, sc->NIL); + if (sc->fcells < n) { + /* If there still aren't, try getting more heap */ + if (!alloc_cellseg(sc,1)) { + sc->no_memory=1; + return sc->NIL; + } + } + if (sc->fcells < n) { + /* If all fail, report failure */ + sc->no_memory=1; + return sc->NIL; + } + } + return (sc->T); +} + +static pointer get_consecutive_cells(scheme *sc, int n) { + pointer x; + + if(sc->no_memory) { return sc->sink; } + + /* Are there any cells available? */ + x=find_consecutive_cells(sc,n); + if (x != sc->NIL) { return x; } + + /* If not, try gc'ing some */ + gc(sc, sc->NIL, sc->NIL); + x=find_consecutive_cells(sc,n); + if (x != sc->NIL) { return x; } + + /* If there still aren't, try getting more heap */ + if (!alloc_cellseg(sc,1)) + { + sc->no_memory=1; + return sc->sink; + } + + x=find_consecutive_cells(sc,n); + if (x != sc->NIL) { return x; } + + /* If all fail, report failure */ + sc->no_memory=1; + return sc->sink; +} + +static int count_consecutive_cells(pointer x, int needed) { + int n=1; + while(cdr(x)==x+1) { + x=cdr(x); + n++; + if(n>needed) return n; + } + return n; +} + +static pointer find_consecutive_cells(scheme *sc, int n) { + pointer *pp; + int cnt; + + pp=&sc->free_cell; + while(*pp!=sc->NIL) { + cnt=count_consecutive_cells(*pp,n); + if(cnt>=n) { + pointer x=*pp; + *pp=cdr(*pp+n-1); + sc->fcells -= n; + return x; + } + pp=&cdr(*pp+cnt-1); + } + return sc->NIL; +} + +/* To retain recent allocs before interpreter knows about them - + Tehom */ + +static void push_recent_alloc(scheme *sc, pointer recent, pointer extra) +{ + pointer holder = get_cell_x(sc, recent, extra); + typeflag(holder) = T_PAIR | T_IMMUTABLE; + car(holder) = recent; + cdr(holder) = car(sc->sink); + car(sc->sink) = holder; +} + + +static pointer get_cell(scheme *sc, pointer a, pointer b) +{ + pointer cell = get_cell_x(sc, a, b); + /* For right now, include "a" and "b" in "cell" so that gc doesn't + think they are garbage. */ + /* Tentatively record it as a pair so gc understands it. */ + typeflag(cell) = T_PAIR; + car(cell) = a; + cdr(cell) = b; + push_recent_alloc(sc, cell, sc->NIL); + return cell; +} + +static pointer get_vector_object(scheme *sc, int len, pointer init) +{ + pointer cells = get_consecutive_cells(sc,len/2+len%2+1); + if(sc->no_memory) { return sc->sink; } + /* Record it as a vector so that gc understands it. */ + typeflag(cells) = (T_VECTOR | T_ATOM); + ivalue_unchecked(cells)=len; + set_num_integer(cells); + fill_vector(cells,init); + push_recent_alloc(sc, cells, sc->NIL); + return cells; +} + +static INLINE void ok_to_freely_gc(scheme *sc) +{ + car(sc->sink) = sc->NIL; +} + + +#if defined TSGRIND +static void check_cell_alloced(pointer p, int expect_alloced) +{ + /* Can't use putstr(sc,str) because callers have no access to + sc. */ + if(typeflag(p) & !expect_alloced) + { + fprintf(stderr,"Cell is already allocated!\n"); + } + if(!(typeflag(p)) & expect_alloced) + { + fprintf(stderr,"Cell is not allocated!\n"); + } +} +static void check_range_alloced(pointer p, int n, int expect_alloced) +{ + int i; + for(i = 0;i<n;i++) + { (void)check_cell_alloced(p+i,expect_alloced); } +} + +#endif + +/* Medium level cell allocation */ + +/* get new cons cell */ +pointer _cons(scheme *sc, pointer a, pointer b, int immutable) { + pointer x = get_cell(sc,a, b); + + typeflag(x) = T_PAIR; + if(immutable) { + setimmutable(x); + } + car(x) = a; + cdr(x) = b; + return (x); +} + +/* ========== oblist implementation ========== */ + +#ifndef USE_OBJECT_LIST + +static int hash_fn(const char *key, int table_size); + +static pointer oblist_initial_value(scheme *sc) +{ + return mk_vector(sc, 461); /* probably should be bigger */ +} + +/* returns the new symbol */ +static pointer oblist_add_by_name(scheme *sc, const char *name) +{ + pointer x; + int location; + + x = immutable_cons(sc, mk_string(sc, name), sc->NIL); + typeflag(x) = T_SYMBOL; + setimmutable(car(x)); + + location = hash_fn(name, ivalue_unchecked(sc->oblist)); + set_vector_elem(sc->oblist, location, + immutable_cons(sc, x, vector_elem(sc->oblist, location))); + return x; +} + +static INLINE pointer oblist_find_by_name(scheme *sc, const char *name) +{ + int location; + pointer x; + char *s; + + location = hash_fn(name, ivalue_unchecked(sc->oblist)); + for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) { + s = symname(car(x)); + /* case-insensitive, per R5RS section 2. */ + if(stricmp(name, s) == 0) { + return car(x); + } + } + return sc->NIL; +} + +static pointer oblist_all_symbols(scheme *sc) +{ + int i; + pointer x; + pointer ob_list = sc->NIL; + + for (i = 0; i < ivalue_unchecked(sc->oblist); i++) { + for (x = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) { + ob_list = cons(sc, x, ob_list); + } + } + return ob_list; +} + +#else + +static pointer oblist_initial_value(scheme *sc) +{ + return sc->NIL; +} + +static INLINE pointer oblist_find_by_name(scheme *sc, const char *name) +{ + pointer x; + char *s; + + for (x = sc->oblist; x != sc->NIL; x = cdr(x)) { + s = symname(car(x)); + /* case-insensitive, per R5RS section 2. */ + if(stricmp(name, s) == 0) { + return car(x); + } + } + return sc->NIL; +} + +/* returns the new symbol */ +static pointer oblist_add_by_name(scheme *sc, const char *name) +{ + pointer x; + + x = immutable_cons(sc, mk_string(sc, name), sc->NIL); + typeflag(x) = T_SYMBOL; + setimmutable(car(x)); + sc->oblist = immutable_cons(sc, x, sc->oblist); + return x; +} + +static pointer oblist_all_symbols(scheme *sc) +{ + return sc->oblist; +} + +#endif + +static pointer mk_port(scheme *sc, port *p) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + + typeflag(x) = T_PORT|T_ATOM; + x->_object._port=p; + return (x); +} + +pointer mk_foreign_func(scheme *sc, foreign_func f) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + + typeflag(x) = (T_FOREIGN | T_ATOM); + x->_object._ff=f; + return (x); +} + +INTERFACE pointer mk_character(scheme *sc, gunichar c) { + pointer x = get_cell(sc,sc->NIL, sc->NIL); + + typeflag(x) = (T_CHARACTER | T_ATOM); + ivalue_unchecked(x)= c; + set_num_integer(x); + return (x); +} + +/* get number atom (integer) */ +INTERFACE pointer mk_integer(scheme *sc, long num) { + pointer x = get_cell(sc,sc->NIL, sc->NIL); + + typeflag(x) = (T_NUMBER | T_ATOM); + ivalue_unchecked(x)= num; + set_num_integer(x); + return (x); +} + +INTERFACE pointer mk_real(scheme *sc, double n) { + pointer x = get_cell(sc,sc->NIL, sc->NIL); + + typeflag(x) = (T_NUMBER | T_ATOM); + rvalue_unchecked(x)= n; + set_num_real(x); + return (x); +} + +static pointer mk_number(scheme *sc, num n) { + if(n.is_fixnum) { + return mk_integer(sc,n.value.ivalue); + } else { + return mk_real(sc,n.value.rvalue); + } +} + +pointer foreign_error (scheme *sc, const char *s, pointer a) { + sc->foreign_error = cons (sc, mk_string (sc, s), a); + return sc->T; +} + +/* char_cnt is length of string in chars. */ +/* str points to a NUL terminated string. */ +/* Only uses fill_char if str is NULL. */ +/* This routine automatically adds 1 byte */ +/* to allow space for terminating NUL. */ +static char *store_string(scheme *sc, int char_cnt, + const char *str, gunichar fill) { + int len; + int i; + gchar utf8[7]; + gchar *q; + gchar *q2; + + if(str!=0) { + q2 = g_utf8_offset_to_pointer(str, (long)char_cnt); + (void)g_utf8_validate(str, -1, (const gchar **)&q); + if (q <= q2) + len = q - str; + else + len = q2 - str; + q=(gchar*)sc->malloc(len+1); + } else { + len = g_unichar_to_utf8(fill, utf8); + q=(gchar*)sc->malloc(char_cnt*len+1); + } + + if(q==0) { + sc->no_memory=1; + return sc->strbuff; + } + if(str!=0) { + memcpy(q, str, len); + q[len]=0; + } else { + q2 = q; + for (i = 0; i < char_cnt; ++i) + { + memcpy(q2, utf8, len); + q2 += len; + } + *q2=0; + } + return (q); +} + +/* get new string */ +INTERFACE pointer mk_string(scheme *sc, const char *str) { + return mk_counted_string(sc,str,g_utf8_strlen(str, -1)); +} + +/* str points to a NUL terminated string. */ +/* len is the length of str in characters */ +INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + + typeflag(x) = (T_STRING | T_ATOM); + strvalue(x) = store_string(sc,len,str,0); + strlength(x) = len; + return (x); +} + +/* len is the length for the empty string in characters */ +INTERFACE pointer mk_empty_string(scheme *sc, int len, gunichar fill) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + + typeflag(x) = (T_STRING | T_ATOM); + strvalue(x) = store_string(sc,len,0,fill); + strlength(x) = len; + return (x); +} + +INTERFACE static pointer mk_vector(scheme *sc, int len) +{ return get_vector_object(sc,len,sc->NIL); } + +INTERFACE static void fill_vector(pointer vec, pointer obj) { + int i; + int num=ivalue(vec)/2+ivalue(vec)%2; + for(i=0; i<num; i++) { + typeflag(vec+1+i) = T_PAIR; + setimmutable(vec+1+i); + car(vec+1+i)=obj; + cdr(vec+1+i)=obj; + } +} + +INTERFACE static pointer vector_elem(pointer vec, int ielem) { + int n=ielem/2; + if(ielem%2==0) { + return car(vec+1+n); + } else { + return cdr(vec+1+n); + } +} + +INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) { + int n=ielem/2; + if(ielem%2==0) { + return car(vec+1+n)=a; + } else { + return cdr(vec+1+n)=a; + } +} + +/* get new symbol */ +INTERFACE pointer mk_symbol(scheme *sc, const char *name) { + pointer x; + + /* first check oblist */ + x = oblist_find_by_name(sc, name); + if (x != sc->NIL) { + return (x); + } else { + x = oblist_add_by_name(sc, name); + return (x); + } +} + +INTERFACE pointer gensym(scheme *sc) { + pointer x; + char name[40]; + + for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) { + snprintf(name,40,"gensym-%ld",sc->gensym_cnt); + + /* first check oblist */ + x = oblist_find_by_name(sc, name); + + if (x != sc->NIL) { + continue; + } else { + x = oblist_add_by_name(sc, name); + return (x); + } + } + + return sc->NIL; +} + +/* make symbol or number atom from string */ +static pointer mk_atom(scheme *sc, char *q) { + char c, *p; + int has_dec_point=0; + int has_fp_exp = 0; + +#if USE_COLON_HOOK + if((p=strstr(q,"::"))!=0) { + *p=0; + return cons(sc, sc->COLON_HOOK, + cons(sc, + cons(sc, + sc->QUOTE, + cons(sc, mk_atom(sc,p+2), sc->NIL)), + cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL))); + } +#endif + + p = q; + c = *p++; + if ((c == '+') || (c == '-')) { + c = *p++; + if (c == '.') { + has_dec_point=1; + c = *p++; + } + if (!isdigit(c)) { + return (mk_symbol(sc, strlwr(q))); + } + } else if (c == '.') { + has_dec_point=1; + c = *p++; + if (!isdigit(c)) { + return (mk_symbol(sc, strlwr(q))); + } + } else if (!isdigit(c)) { + return (mk_symbol(sc, strlwr(q))); + } + + for ( ; (c = *p) != 0; ++p) { + if (!isdigit(c)) { + if(c=='.') { + if(!has_dec_point) { + has_dec_point=1; + continue; + } + } + else if ((c == 'e') || (c == 'E')) { + if(!has_fp_exp) { + has_dec_point = 1; /* decimal point illegal + from now on */ + p++; + if ((*p == '-') || (*p == '+') || isdigit(*p)) { + continue; + } + } + } + return (mk_symbol(sc, strlwr(q))); + } + } + if(has_dec_point) { + return mk_real(sc,g_ascii_strtod(q,NULL)); + } + return (mk_integer(sc, atol(q))); +} + +/* make constant */ +static pointer mk_sharp_const(scheme *sc, char *name) { + long x; + char tmp[STRBUFFSIZE]; + + if (!strcmp(name, "t")) + return (sc->T); + else if (!strcmp(name, "f")) + return (sc->F); + else if (*name == 'o') {/* #o (octal) */ + snprintf(tmp, STRBUFFSIZE, "0%s", name+1); + sscanf(tmp, "%lo", (long unsigned *)&x); + return (mk_integer(sc, x)); + } else if (*name == 'd') { /* #d (decimal) */ + sscanf(name+1, "%ld", (long int *)&x); + return (mk_integer(sc, x)); + } else if (*name == 'x') { /* #x (hex) */ + snprintf(tmp, STRBUFFSIZE, "0x%s", name+1); + sscanf(tmp, "%lx", (long unsigned *)&x); + return (mk_integer(sc, x)); + } else if (*name == 'b') { /* #b (binary) */ + x = binary_decode(name+1); + return (mk_integer(sc, x)); + } else if (*name == '\\') { /* #\w (character) */ + gunichar c=0; + if(stricmp(name+1,"space")==0) { + c=' '; + } else if(stricmp(name+1,"newline")==0) { + c='\n'; + } else if(stricmp(name+1,"return")==0) { + c='\r'; + } else if(stricmp(name+1,"tab")==0) { + c='\t'; + } else if(name[1]=='x' && name[2]!=0) { + int c1=0; + if(sscanf(name+2,"%x",(unsigned int *)&c1)==1 && c1 < UCHAR_MAX) { + c=c1; + } else { + return sc->NIL; + } +#if USE_ASCII_NAMES + } else if(is_ascii_name(name+1,&c)) { + /* nothing */ +#endif + } else if(name[2]==0) { + c=name[1]; + } else { + return sc->NIL; + } + return mk_character(sc,c); + } else + return (sc->NIL); +} + +/* ========== garbage collector ========== */ + +/*-- + * We use algorithm E (Knuth, The Art of Computer Programming Vol.1, + * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm, + * for marking. + */ +static void mark(pointer a) { + pointer t, q, p; + + t = (pointer) 0; + p = a; +E2: setmark(p); + if(is_vector(p)) { + int i; + int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2; + for(i=0; i<num; i++) { + /* Vector cells will be treated like ordinary cells */ + mark(p+1+i); + } + } + if (is_atom(p)) + goto E6; + /* E4: down car */ + q = car(p); + if (q && !is_mark(q)) { + setatom(p); /* a note that we have moved car */ + car(p) = t; + t = p; + p = q; + goto E2; + } + E5: q = cdr(p); /* down cdr */ + if (q && !is_mark(q)) { + cdr(p) = t; + t = p; + p = q; + goto E2; + } +E6: /* up. Undo the link switching from steps E4 and E5. */ + if (!t) + return; + q = t; + if (is_atom(q)) { + clratom(q); + t = car(q); + car(q) = p; + p = q; + goto E5; + } else { + t = cdr(q); + cdr(q) = p; + p = q; + goto E6; + } +} + +/* garbage collection. parameter a, b is marked. */ +static void gc(scheme *sc, pointer a, pointer b) { + pointer p; + int i; + + if(sc->gc_verbose) { + putstr(sc, "gc..."); + } + + /* mark system globals */ + mark(sc->oblist); + mark(sc->global_env); + + /* mark current registers */ + mark(sc->args); + mark(sc->envir); + mark(sc->code); + dump_stack_mark(sc); + mark(sc->value); + mark(sc->inport); + mark(sc->save_inport); + mark(sc->outport); + mark(sc->loadport); + + /* Mark recent objects the interpreter doesn't know about yet. */ + mark(car(sc->sink)); + /* Mark any older stuff above nested C calls */ + mark(sc->c_nest); + + /* mark variables a, b */ + mark(a); + mark(b); + + /* garbage collect */ + clrmark(sc->NIL); + sc->fcells = 0; + sc->free_cell = sc->NIL; + /* free-list is kept sorted by address so as to maintain consecutive + ranges, if possible, for use with vectors. Here we scan the cells + (which are also kept sorted by address) downwards to build the + free-list in sorted order. + */ + for (i = sc->last_cell_seg; i >= 0; i--) { + p = sc->cell_seg[i] + CELL_SEGSIZE; + while (--p >= sc->cell_seg[i]) { + if (is_mark(p)) { + clrmark(p); + } else { + /* reclaim cell */ + if (typeflag(p) != 0) { + finalize_cell(sc, p); + typeflag(p) = 0; + car(p) = sc->NIL; + } + ++sc->fcells; + cdr(p) = sc->free_cell; + sc->free_cell = p; + } + } + } + + if (sc->gc_verbose) { + char msg[80]; + snprintf(msg,80,"done: %ld cells were recovered.\n", sc->fcells); + putstr(sc,msg); + } +} + +static void finalize_cell(scheme *sc, pointer a) { + if(is_string(a)) { + sc->free(strvalue(a)); + } else if(is_port(a)) { + if(a->_object._port->kind&port_file + && a->_object._port->rep.stdio.closeit) { + port_close(sc,a,port_input|port_output); + } + sc->free(a->_object._port); + } +} + +/* ========== Routines for Reading ========== */ + +static int file_push(scheme *sc, const char *fname) { + FILE *fin = NULL; + if (sc->file_i == MAXFIL-1) + return 0; + + fin=g_fopen(fname,"rb"); + if(fin!=0) { + sc->file_i++; + sc->load_stack[sc->file_i].kind=port_file|port_input; + sc->load_stack[sc->file_i].rep.stdio.file=fin; + sc->load_stack[sc->file_i].rep.stdio.closeit=1; + sc->nesting_stack[sc->file_i]=0; + sc->loadport->_object._port=sc->load_stack+sc->file_i; + +#if SHOW_ERROR_LINE + sc->load_stack[sc->file_i].rep.stdio.curr_line = 0; + if(fname) + sc->load_stack[sc->file_i].rep.stdio.filename = store_string(sc, strlen(fname), fname, 0); +#endif + } + return fin!=0; +} + +static void file_pop(scheme *sc) { + if(sc->file_i != 0) { + sc->nesting=sc->nesting_stack[sc->file_i]; + port_close(sc,sc->loadport,port_input); + sc->file_i--; + sc->loadport->_object._port=sc->load_stack+sc->file_i; + } +} + +static int file_interactive(scheme *sc) { + return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin + && sc->inport->_object._port->kind&port_file; +} + +static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) { + FILE *f; + char *rw; + port *pt; + if(prop==(port_input|port_output)) { + rw="a+b"; + } else if(prop==port_output) { + rw="wb"; + } else { + rw="rb"; + } + f=g_fopen(fn,rw); + if(f==0) { + return 0; + } + pt=port_rep_from_file(sc,f,prop); + pt->rep.stdio.closeit=1; + +#if SHOW_ERROR_LINE + if(fn) + pt->rep.stdio.filename = store_string(sc, strlen(fn), fn, 0); + + pt->rep.stdio.curr_line = 0; +#endif + return pt; +} + +static pointer port_from_filename(scheme *sc, const char *fn, int prop) { + port *pt; + pt=port_rep_from_filename(sc,fn,prop); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +static port *port_rep_from_file(scheme *sc, FILE *f, int prop) +{ + port *pt; + + pt = (port *)sc->malloc(sizeof *pt); + if (pt == NULL) { + return NULL; + } + pt->kind = port_file | prop; + pt->rep.stdio.file = f; + pt->rep.stdio.closeit = 0; + return pt; +} + +static pointer port_from_file(scheme *sc, FILE *f, int prop) { + port *pt; + pt=port_rep_from_file(sc,f,prop); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) { + port *pt; + pt=(port*)sc->malloc(sizeof(port)); + if(pt==0) { + return 0; + } + pt->kind=port_string|prop; + pt->rep.string.start=start; + pt->rep.string.curr=start; + pt->rep.string.past_the_end=past_the_end; + return pt; +} + +static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) { + port *pt; + pt=port_rep_from_string(sc,start,past_the_end,prop); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +#define BLOCK_SIZE 256 + +static port *port_rep_from_scratch(scheme *sc) { + port *pt; + char *start; + pt=(port*)sc->malloc(sizeof(port)); + if(pt==0) { + return 0; + } + start=sc->malloc(BLOCK_SIZE); + if(start==0) { + return 0; + } + memset(start,' ',BLOCK_SIZE-1); + start[BLOCK_SIZE-1]='\0'; + pt->kind=port_string|port_output|port_srfi6; + pt->rep.string.start=start; + pt->rep.string.curr=start; + pt->rep.string.past_the_end=start+BLOCK_SIZE-1; + return pt; +} + +static pointer port_from_scratch(scheme *sc) { + port *pt; + pt=port_rep_from_scratch(sc); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +static void port_close(scheme *sc, pointer p, int flag) { + port *pt=p->_object._port; + pt->kind&=~flag; + if((pt->kind & (port_input|port_output))==0) { + if(pt->kind&port_file) { + +#if SHOW_ERROR_LINE + /* Cleanup is here so (close-*-port) functions could work too */ + pt->rep.stdio.curr_line = 0; + + if(pt->rep.stdio.filename) + sc->free(pt->rep.stdio.filename); +#endif + + fclose(pt->rep.stdio.file); + } + pt->kind=port_free; + } +} + +/* This routine will ignore byte sequences that are not valid UTF-8 */ +static gunichar basic_inchar(port *pt) { + if(pt->kind & port_file) { + int c; + + c = fgetc(pt->rep.stdio.file); + + while (TRUE) + { + if (c == EOF) return EOF; + + if (c <= 0x7f) + return (gunichar) c; + + /* Is this byte an invalid lead per RFC-3629? */ + if (c < 0xc2 || c > 0xf4) + { + /* Ignore invalid lead byte and get the next character */ + c = fgetc(pt->rep.stdio.file); + } + else /* Byte is valid lead */ + { + unsigned char utf8[7]; + int len; + int i; + + utf8[0] = c; /* Save the lead byte */ + + len = utf8_length[c & 0x3F]; + for (i = 1; i <= len; i++) + { + c = fgetc(pt->rep.stdio.file); + + /* Stop reading if this is not a continuation character */ + if ((c & 0xc0) != 0x80) + break; + + utf8[i] = c; + } + + if (i > len) /* Read the expected number of bytes? */ + { + return g_utf8_get_char_validated ((char *) utf8, + sizeof(utf8)); + } + + /* Not enough continuation characters so ignore and restart */ + } + } /* end of while (TRUE) */ + } else { + gunichar c; + int len; + + while (TRUE) + { + /* Found NUL or at end of input buffer? */ + if (*pt->rep.string.curr == 0 || + pt->rep.string.curr == pt->rep.string.past_the_end) { + return EOF; + } + + len = pt->rep.string.past_the_end - pt->rep.string.curr; + c = g_utf8_get_char_validated(pt->rep.string.curr, len); + + if (c != (gunichar) -1 && + c != (gunichar) -2) /* Valid UTF-8 character? */ + { + len = g_unichar_to_utf8(c, NULL); /* Length of UTF-8 sequence */ + pt->rep.string.curr += len; + return c; + } + + /* Look for next valid UTF-8 character in buffer */ + pt->rep.string.curr = g_utf8_find_next_char(pt->rep.string.curr, + pt->rep.string.past_the_end); + } /* end of while (TRUE) */ + } +} + +/* get new character from input file */ +static gunichar inchar(scheme *sc) { + gunichar c; + port *pt; + + pt = sc->inport->_object._port; + if(pt->kind & port_saw_EOF) + { return(EOF); } + if(pt->kind&port_file) + { + if (sc->bc_flag) + c = sc->backchar[--sc->bc_flag]; + else + c = basic_inchar(pt); + } + else + c = basic_inchar(pt); + if(c == EOF && sc->inport == sc->loadport) { + /* Instead, set port_saw_EOF */ + pt->kind |= port_saw_EOF; + + /* file_pop(sc); */ + return EOF; + /* NOTREACHED */ + } + return c; +} + +/* back character to input buffer */ +static void backchar(scheme *sc, gunichar c) { + port *pt; + gint charlen; + + if(c==EOF) return; + charlen = g_unichar_to_utf8(c, NULL); + pt=sc->inport->_object._port; + if(pt->kind&port_file) { + if (sc->bc_flag < 2) + sc->backchar[sc->bc_flag++] = c; + } else { + if(pt->rep.string.curr!=pt->rep.string.start) { + if(pt->rep.string.curr-pt->rep.string.start >= charlen) + pt->rep.string.curr -= charlen; + else + pt->rep.string.curr = pt->rep.string.start; + } + } +} + +static int realloc_port_string(scheme *sc, port *p) +{ + char *start=p->rep.string.start; + size_t new_size=p->rep.string.past_the_end-start+1+BLOCK_SIZE; + char *str=sc->malloc(new_size); + if(str) { + memset(str,' ',new_size-1); + str[new_size-1]='\0'; + strcpy(str,start); + p->rep.string.start=str; + p->rep.string.past_the_end=str+new_size-1; + p->rep.string.curr-=start-str; + sc->free(start); + return 1; + } else { + return 0; + } +} + +/* len is number of UTF-8 characters in string pointed to by chars */ +static void putchars(scheme *sc, const char *chars, int char_cnt) { + int free_bytes; /* Space remaining in buffer (in bytes) */ + int l; + port *pt=sc->outport->_object._port; + + if (char_cnt <= 0) + return; + + /* Get length of 'chars' in bytes */ + char_cnt = g_utf8_offset_to_pointer(chars, (long)char_cnt) - chars; + + if(pt->kind&port_file) { +#if STANDALONE + fwrite(chars,1,char_cnt,pt->rep.stdio.file); + fflush(pt->rep.stdio.file); +#else + /* If output is still directed to stdout (the default) it should be */ + /* safe to redirect it to the registered output routine. */ + if (pt->rep.stdio.file == stdout) + ts_output_string (TS_OUTPUT_NORMAL, chars, char_cnt); + else { + fwrite(chars,1,char_cnt,pt->rep.stdio.file); + fflush(pt->rep.stdio.file); + } +#endif + } else { + if (pt->rep.string.past_the_end != pt->rep.string.curr) + { + free_bytes = pt->rep.string.past_the_end - pt->rep.string.curr; + l = min(char_cnt, free_bytes); + memcpy(pt->rep.string.curr, chars, l); + pt->rep.string.curr += l; + } + else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) + { + free_bytes = pt->rep.string.past_the_end - pt->rep.string.curr; + l = min(char_cnt, free_bytes); + memcpy(pt->rep.string.curr, chars, char_cnt); + pt->rep.string.curr += l; + } + } +} + +INTERFACE void putcharacter(scheme *sc, gunichar c) { + char utf8[7]; + + (void)g_unichar_to_utf8(c, utf8); + putchars(sc, utf8, 1); +} + +INTERFACE void putstr(scheme *sc, const char *s) { + putchars(sc, s, g_utf8_strlen(s, -1)); +} + +/* read characters up to delimiter, but cater to character constants */ +static char *readstr_upto(scheme *sc, char *delim) { + char *p = sc->strbuff; + gunichar c = 0; + gunichar c_prev = 0; + int len = 0; + + do { + c_prev = c; + c = inchar(sc); + len = g_unichar_to_utf8(c, p); + p += len; + } while ((p - sc->strbuff < sizeof(sc->strbuff)) && + (c && !is_one_of(delim, c))); + + if(p == sc->strbuff+2 && c_prev == '\\') + *p = '\0'; + else + { + backchar(sc,c); /* put back the delimiter */ + p[-len] = '\0'; + } + return sc->strbuff; +} + +/* read string expression "xxx...xxx" */ +static pointer readstrexp(scheme *sc) { + char *p = sc->strbuff; + gunichar c; + int c1=0; + int len; + enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2 } state=st_ok; + + for (;;) { + c=inchar(sc); + if(c == EOF || p-sc->strbuff > sizeof(sc->strbuff)-1) { + return sc->F; + } + switch(state) { + case st_ok: + switch(c) { + case '\\': + state=st_bsl; + break; + case '"': + *p=0; + return mk_counted_string(sc,sc->strbuff, + g_utf8_strlen(sc->strbuff, sizeof(sc->strbuff))); + default: + len = g_unichar_to_utf8(c, p); + p += len; + break; + } + break; + case st_bsl: + switch(c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + state=st_oct1; + c1=g_unichar_digit_value(c); + break; + case 'x': + case 'X': + state=st_x1; + c1=0; + break; + case 'n': + *p++='\n'; + state=st_ok; + break; + case 't': + *p++='\t'; + state=st_ok; + break; + case 'r': + *p++='\r'; + state=st_ok; + break; + case '"': + *p++='"'; + state=st_ok; + break; + default: + len = g_unichar_to_utf8(c, p); + p += len; + state=st_ok; + break; + } + break; + case st_x1: + case st_x2: + if (!g_unichar_isxdigit(c)) + return sc->F; + c1=(c1<<4)+g_unichar_xdigit_value(c); + if(state==st_x1) + state=st_x2; + else { + *p++=c1; + state=st_ok; + } + break; + case st_oct1: /* State when handling second octal digit */ + case st_oct2: /* State when handling third octal digit */ + if (!g_unichar_isdigit(c) || g_unichar_digit_value(c) > 7) + { + *p++=c1; + backchar(sc, c); + state=st_ok; + } + else + { + /* Is value of three character octal too big for a byte? */ + if (state==st_oct2 && c1 >= 32) + return sc->F; + + c1=(c1<<3)+g_unichar_digit_value(c); + + if (state == st_oct1) + state=st_oct2; + else + { + *p++=c1; + state=st_ok; + } + } + break; + } + } +} + +/* check c is in chars */ +static INLINE int is_one_of(char *s, gunichar c) { + if (c==EOF) + return 1; + + if (g_utf8_strchr(s, -1, c) != NULL) + return (1); + + return (0); +} + +/* skip white characters */ +static INLINE int skipspace(scheme *sc) { + gunichar c; + int curr_line = 0; + do { + c=inchar(sc); +#if SHOW_ERROR_LINE + if(c=='\n') + curr_line++; +#endif + } while (g_unichar_isspace(c)); + +/* record it */ +#if SHOW_ERROR_LINE + if (sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line += curr_line; +#endif + + if(c!=EOF) { + backchar(sc,c); + return 1; + } + else + { return EOF; } +} + +/* get token */ +static int token(scheme *sc) { + gunichar c; + c = skipspace(sc); + if(c == EOF) { return (TOK_EOF); } + switch (c=inchar(sc)) { + case EOF: + return (TOK_EOF); + case '(': + return (TOK_LPAREN); + case ')': + return (TOK_RPAREN); + case '.': + c=inchar(sc); + if(is_one_of(" \n\t",c)) { + return (TOK_DOT); + } else { + backchar(sc,c); + backchar(sc,'.'); + return TOK_ATOM; + } + case '\'': + return (TOK_QUOTE); + case ';': + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + +#if SHOW_ERROR_LINE + if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line++; +#endif + + if(c == EOF) + { return (TOK_EOF); } + else + { return (token(sc));} + case '"': + return (TOK_DQUOTE); + case '_': + if ((c=inchar(sc)) == '"') + return (TOK_USCORE); + backchar(sc,c); + return (TOK_ATOM); + case BACKQUOTE: + return (TOK_BQUOTE); + case ',': + if ((c=inchar(sc)) == '@') { + return (TOK_ATMARK); + } else { + backchar(sc,c); + return (TOK_COMMA); + } + case '#': + c=inchar(sc); + if (c == '(') { + return (TOK_VEC); + } else if(c == '!') { + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + +#if SHOW_ERROR_LINE + if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line++; +#endif + + if(c == EOF) + { return (TOK_EOF); } + else + { return (token(sc));} + } else { + backchar(sc,c); + if(is_one_of(" tfodxb\\",c)) { + return TOK_SHARP_CONST; + } else { + return (TOK_SHARP); + } + } + default: + backchar(sc,c); + return (TOK_ATOM); + } +} + +/* ========== Routines for Printing ========== */ +#define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL) + +static void printslashstring(scheme *sc, char *p, int len) { + int i; + gunichar c; + char *s=(char*)p; + + putcharacter(sc,'"'); + for (i=0; i<len; i++) { + c = g_utf8_get_char(s); + /* Is a check for a value of 0xff still valid in UTF8?? ~~~~~ */ + if(c==0xff || c=='"' || c<' ' || c=='\\') { + putcharacter(sc,'\\'); + switch(c) { + case '"': + putcharacter(sc,'"'); + break; + case '\n': + putcharacter(sc,'n'); + break; + case '\t': + putcharacter(sc,'t'); + break; + case '\r': + putcharacter(sc,'r'); + break; + case '\\': + putcharacter(sc,'\\'); + break; + default: { + /* This still needs work ~~~~~ */ + int d=c/16; + putcharacter(sc,'x'); + if(d<10) { + putcharacter(sc,d+'0'); + } else { + putcharacter(sc,d-10+'A'); + } + d=c%16; + if(d<10) { + putcharacter(sc,d+'0'); + } else { + putcharacter(sc,d-10+'A'); + } + } + } + } else { + putcharacter(sc,c); + } + s = g_utf8_next_char(s); + } + putcharacter(sc,'"'); +} + + +/* print atoms */ +static void printatom(scheme *sc, pointer l, int f) { + char *p; + int len; + atom2str(sc,l,f,&p,&len); + putchars(sc,p,len); +} + + +/* Uses internal buffer unless string pointer is already available */ +static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen) { + char *p; + + if (l == sc->NIL) { + p = "()"; + } else if (l == sc->T) { + p = "#t"; + } else if (l == sc->F) { + p = "#f"; + } else if (l == sc->EOF_OBJ) { + p = "#<EOF>"; + } else if (is_port(l)) { + p = "#<PORT>"; + } else if (is_number(l)) { + p = sc->strbuff; + if (f <= 1 || f == 10) /* f is the base for numbers if > 1 */ { + if(num_is_integer(l)) { + snprintf(p, STRBUFFSIZE, "%ld", ivalue_unchecked(l)); + } else { + snprintf(p, STRBUFFSIZE, "%.10g", rvalue_unchecked(l)); + /* r5rs says there must be a '.' (unless 'e'?) */ + f = strcspn(p, ".e"); + if (p[f] == 0) { + p[f] = '.'; /* not found, so add '.0' at the end */ + p[f+1] = '0'; + p[f+2] = 0; + } + } + } else { + long v = ivalue(l); + if (f == 16) { + if (v >= 0) + snprintf(p, STRBUFFSIZE, "%lx", v); + else + snprintf(p, STRBUFFSIZE, "-%lx", -v); + } else if (f == 8) { + if (v >= 0) + snprintf(p, STRBUFFSIZE, "%lo", v); + else + snprintf(p, STRBUFFSIZE, "-%lo", -v); + } else if (f == 2) { + unsigned long b = (v < 0) ? -v : v; + p = &p[STRBUFFSIZE-1]; + *p = 0; + do { *--p = (b&1) ? '1' : '0'; b >>= 1; } while (b != 0); + if (v < 0) *--p = '-'; + } + } + } else if (is_string(l)) { + if (!f) { + p = strvalue(l); + } else { /* Hack, uses the fact that printing is needed */ + *pp=sc->strbuff; + *plen=0; + printslashstring(sc, strvalue(l), + g_utf8_strlen(strvalue(l), -1)); + return; + } + } else if (is_character(l)) { + gunichar c=charvalue(l); + p = sc->strbuff; + if (!f) { + int len = g_unichar_to_utf8(c, p); + p[len]=0; + } else { + switch(c) { + case ' ': + p = "#\\space"; + break; + case '\n': + p = "#\\newline"; + break; + case '\r': + p = "#\\return"; + break; + case '\t': + p = "#\\tab"; + break; + default: +#if USE_ASCII_NAMES + if(c==127) { + p = "#\\del"; + break; + } else if(c<32) { + snprintf(p,STRBUFFSIZE, "#\\%s", charnames[c]); + break; + } +#else + if(c<32) { + snprintf(p,STRBUFFSIZE,"#\\x%x",c); + break; + } +#endif + snprintf(p,STRBUFFSIZE,"#\\%c",c); + break; + } + } + } else if (is_symbol(l)) { + p = symname(l); + } else if (is_proc(l)) { + p = sc->strbuff; + snprintf(p,STRBUFFSIZE,"#<%s PROCEDURE %ld>", + procname(l),procnum(l)); + } else if (is_macro(l)) { + p = "#<MACRO>"; + } else if (is_closure(l)) { + p = "#<CLOSURE>"; + } else if (is_promise(l)) { + p = "#<PROMISE>"; + } else if (is_foreign(l)) { + p = sc->strbuff; + snprintf(p,STRBUFFSIZE,"#<FOREIGN PROCEDURE %ld>", procnum(l)); + } else if (is_continuation(l)) { + p = "#<CONTINUATION>"; + } else { + p = "#<ERROR>"; + } + *pp=p; + *plen=g_utf8_strlen(p, -1); +} +/* ========== Routines for Evaluation Cycle ========== */ + +/* make closure. c is code. e is environment */ +static pointer mk_closure(scheme *sc, pointer c, pointer e) { + pointer x = get_cell(sc, c, e); + + typeflag(x) = T_CLOSURE; + car(x) = c; + cdr(x) = e; + return (x); +} + +/* make continuation. */ +static pointer mk_continuation(scheme *sc, pointer d) { + pointer x = get_cell(sc, sc->NIL, d); + + typeflag(x) = T_CONTINUATION; + cont_dump(x) = d; + return (x); +} + +static pointer list_star(scheme *sc, pointer d) { + pointer p, q; + if(cdr(d)==sc->NIL) { + return car(d); + } + p=cons(sc,car(d),cdr(d)); + q=p; + while(cdr(cdr(p))!=sc->NIL) { + d=cons(sc,car(p),cdr(p)); + if(cdr(cdr(p))!=sc->NIL) { + p=cdr(d); + } + } + cdr(p)=car(cdr(p)); + return q; +} + +/* reverse list -- produce new list */ +static pointer reverse(scheme *sc, pointer a) { +/* a must be checked by gc */ + pointer p = sc->NIL; + + for ( ; is_pair(a); a = cdr(a)) { + p = cons(sc, car(a), p); + } + return (p); +} + +/* reverse list --- in-place */ +static pointer reverse_in_place(scheme *sc, pointer term, pointer list) { + pointer p = list, result = term, q; + + while (p != sc->NIL) { + q = cdr(p); + cdr(p) = result; + result = p; + p = q; + } + return (result); +} + +/* append list -- produce new list */ +static pointer revappend(scheme *sc, pointer a, pointer b) { + pointer result = a; + pointer p = b; + + while (is_pair(p)) { + result = cons(sc, car(p), result); + p = cdr(p); + } + + if (p == sc->NIL) { + return result; + } + + return sc->F; /* signal an error */ +} + +/* equivalence of atoms */ +int eqv(pointer a, pointer b) { + if (is_string(a)) { + if (is_string(b)) + return (strvalue(a) == strvalue(b)); + else + return (0); + } else if (is_number(a)) { + if (is_number(b)) { + if (num_is_integer(a) == num_is_integer(b)) + return num_eq(nvalue(a),nvalue(b)); + } + return (0); + } else if (is_character(a)) { + if (is_character(b)) + return charvalue(a)==charvalue(b); + else + return (0); + } else if (is_port(a)) { + if (is_port(b)) + return a==b; + else + return (0); + } else if (is_proc(a)) { + if (is_proc(b)) + return procnum(a)==procnum(b); + else + return (0); + } else { + return (a == b); + } +} + +/* true or false value macro */ +/* () is #t in R5RS */ +#define is_true(p) ((p) != sc->F) +#define is_false(p) ((p) == sc->F) + +/* ========== Environment implementation ========== */ + +#if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST) + +static int hash_fn(const char *key, int table_size) +{ + unsigned int hashed = 0; + const char *c; + int bits_per_int = sizeof(unsigned int)*8; + + for (c = key; *c; c++) { + /* letters have about 5 bits in them */ + hashed = (hashed<<5) | (hashed>>(bits_per_int-5)); + hashed ^= *c; + } + return hashed % table_size; +} +#endif + +#ifndef USE_ALIST_ENV + +/* + * In this implementation, each frame of the environment may be + * a hash table: a vector of alists hashed by variable name. + * In practice, we use a vector only for the initial frame; + * subsequent frames are too small and transient for the lookup + * speed to out-weigh the cost of making a new vector. + */ + +static void new_frame_in_env(scheme *sc, pointer old_env) +{ + pointer new_frame; + + /* The interaction-environment has about 300 variables in it. */ + if (old_env == sc->NIL) { + new_frame = mk_vector(sc, 461); + } else { + new_frame = sc->NIL; + } + + sc->envir = immutable_cons(sc, new_frame, old_env); + setenvironment(sc->envir); +} + +static INLINE void new_slot_spec_in_env(scheme *sc, pointer env, + pointer variable, pointer value) +{ + pointer slot = immutable_cons(sc, variable, value); + + if (is_vector(car(env))) { + int location = hash_fn(symname(variable), ivalue_unchecked(car(env))); + + set_vector_elem(car(env), location, + immutable_cons(sc, slot, vector_elem(car(env), location))); + } else { + car(env) = immutable_cons(sc, slot, car(env)); + } +} + +static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all) +{ + pointer x,y; + int location; + + for (x = env; x != sc->NIL; x = cdr(x)) { + if (is_vector(car(x))) { + location = hash_fn(symname(hdl), ivalue_unchecked(car(x))); + y = vector_elem(car(x), location); + } else { + y = car(x); + } + for ( ; y != sc->NIL; y = cdr(y)) { + if (caar(y) == hdl) { + break; + } + } + if (y != sc->NIL) { + break; + } + if(!all) { + return sc->NIL; + } + } + if (x != sc->NIL) { + return car(y); + } + return sc->NIL; +} + +#else /* USE_ALIST_ENV */ + +static INLINE void new_frame_in_env(scheme *sc, pointer old_env) +{ + sc->envir = immutable_cons(sc, sc->NIL, old_env); + setenvironment(sc->envir); +} + +static INLINE void new_slot_spec_in_env(scheme *sc, pointer env, + pointer variable, pointer value) +{ + car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env)); +} + +static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all) +{ + pointer x,y; + for (x = env; x != sc->NIL; x = cdr(x)) { + for (y = car(x); y != sc->NIL; y = cdr(y)) { + if (caar(y) == hdl) { + break; + } + } + if (y != sc->NIL) { + break; + } + if(!all) { + return sc->NIL; + } + } + if (x != sc->NIL) { + return car(y); + } + return sc->NIL; +} + +#endif /* USE_ALIST_ENV else */ + +static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value) +{ + new_slot_spec_in_env(sc, sc->envir, variable, value); +} + +static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value) +{ + cdr(slot) = value; +} + +static INLINE pointer slot_value_in_env(pointer slot) +{ + return cdr(slot); +} + +/* ========== Evaluation Cycle ========== */ + + +static pointer _Error_1(scheme *sc, const char *s, pointer a) { + const char *str = s; +#if USE_ERROR_HOOK + pointer x; + pointer hdl=sc->ERROR_HOOK; +#endif + +#if SHOW_ERROR_LINE + char sbuf[STRBUFFSIZE]; + + /* make sure error is not in REPL */ + if (sc->load_stack[sc->file_i].kind & port_file && + sc->load_stack[sc->file_i].rep.stdio.file != stdin) { + int ln = sc->load_stack[sc->file_i].rep.stdio.curr_line; + const char *fname = sc->load_stack[sc->file_i].rep.stdio.filename; + + /* should never happen */ + if(!fname) fname = "<unknown>"; + + /* we started from 0 */ + ln++; + snprintf(sbuf, STRBUFFSIZE, "(%s : %i) %s", fname, ln, s); + + str = (const char*)sbuf; + } +#endif + +#if USE_ERROR_HOOK + x=find_slot_in_env(sc,sc->envir,hdl,1); + if (x != sc->NIL) { + if(a!=0) { + sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL); + } else { + sc->code = sc->NIL; + } + sc->code = cons(sc, mk_string(sc, str), sc->code); + setimmutable(car(sc->code)); + sc->code = cons(sc, slot_value_in_env(x), sc->code); + sc->op = (int)OP_EVAL; + return sc->T; + } +#endif + + if(a!=0) { + sc->args = cons(sc, (a), sc->NIL); + } else { + sc->args = sc->NIL; + } + sc->args = cons(sc, mk_string(sc, str), sc->args); + setimmutable(car(sc->args)); + sc->op = (int)OP_ERR0; + return sc->T; +} +#define Error_1(sc,s,a) return _Error_1(sc,s,a) +#define Error_0(sc,s) return _Error_1(sc,s,0) + +/* Too small to turn into function */ +# define BEGIN do { +# define END } while (0) +#define s_goto(sc,a) BEGIN \ + sc->op = (int)(a); \ + return sc->T; END + +#define s_return(sc,a) return _s_return(sc,a) + +#ifndef USE_SCHEME_STACK + +/* this structure holds all the interpreter's registers */ +struct dump_stack_frame { + enum scheme_opcodes op; + pointer args; + pointer envir; + pointer code; +}; + +#define STACK_GROWTH 3 + +static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) +{ + int nframes = (int)sc->dump; + struct dump_stack_frame *next_frame; + + /* enough room for the next frame? */ + if (nframes >= sc->dump_size) { + sc->dump_size += STACK_GROWTH; + /* alas there is no sc->realloc */ + sc->dump_base = realloc(sc->dump_base, + sizeof(struct dump_stack_frame) * sc->dump_size); + } + next_frame = (struct dump_stack_frame *)sc->dump_base + nframes; + next_frame->op = op; + next_frame->args = args; + next_frame->envir = sc->envir; + next_frame->code = code; + sc->dump = (pointer)(nframes+1); +} + +static pointer _s_return(scheme *sc, pointer a) +{ + int nframes = (int)sc->dump; + struct dump_stack_frame *frame; + + sc->value = (a); + if (nframes <= 0) { + return sc->NIL; + } + nframes--; + frame = (struct dump_stack_frame *)sc->dump_base + nframes; + sc->op = frame->op; + sc->args = frame->args; + sc->envir = frame->envir; + sc->code = frame->code; + sc->dump = (pointer)nframes; + return sc->T; +} + +static INLINE void dump_stack_reset(scheme *sc) +{ + /* in this implementation, sc->dump is the number of frames on the stack */ + sc->dump = (pointer)0; +} + +static INLINE void dump_stack_initialize(scheme *sc) +{ + sc->dump_size = 0; + sc->dump_base = NULL; + dump_stack_reset(sc); +} + +static void dump_stack_free(scheme *sc) +{ + free(sc->dump_base); + sc->dump_base = NULL; + sc->dump = (pointer)0; + sc->dump_size = 0; +} + +static INLINE void dump_stack_mark(scheme *sc) +{ + int nframes = (int)sc->dump; + int i; + for(i=0; i<nframes; i++) { + struct dump_stack_frame *frame; + frame = (struct dump_stack_frame *)sc->dump_base + i; + mark(frame->args); + mark(frame->envir); + mark(frame->code); + } +} + +#else + +static INLINE void dump_stack_reset(scheme *sc) +{ + sc->dump = sc->NIL; +} + +static INLINE void dump_stack_initialize(scheme *sc) +{ + dump_stack_reset(sc); +} + +static void dump_stack_free(scheme *sc) +{ + sc->dump = sc->NIL; +} + +static pointer _s_return(scheme *sc, pointer a) { + sc->value = (a); + if(sc->dump==sc->NIL) return sc->NIL; + sc->op = ivalue(car(sc->dump)); + sc->args = cadr(sc->dump); + sc->envir = caddr(sc->dump); + sc->code = cadddr(sc->dump); + sc->dump = cddddr(sc->dump); + return sc->T; +} + +static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) { + sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump)); + sc->dump = cons(sc, (args), sc->dump); + sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump); +} + +static INLINE void dump_stack_mark(scheme *sc) +{ + mark(sc->dump); +} +#endif + +#define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F) + +static pointer opexe_0(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + + switch (op) { + case OP_LOAD: /* load */ + if(file_interactive(sc)) { + fprintf(sc->outport->_object._port->rep.stdio.file, + "Loading %s\n", strvalue(car(sc->args))); + } + if (!file_push(sc,strvalue(car(sc->args)))) { + Error_1(sc,"unable to open", car(sc->args)); + } + else + { + sc->args = mk_integer(sc,sc->file_i); + s_goto(sc,OP_T0LVL); + } + + case OP_T0LVL: /* top level */ + /* If we reached the end of file, this loop is done. */ + if(sc->loadport->_object._port->kind & port_saw_EOF) + { + if(sc->file_i == 0) + { + sc->args=sc->NIL; + s_goto(sc,OP_QUIT); + } + else + { + file_pop(sc); + s_return(sc,sc->value); + } + /* NOTREACHED */ + } + + /* If interactive, be nice to user. */ + if(file_interactive(sc)) + { + sc->envir = sc->global_env; + dump_stack_reset(sc); + putstr(sc,"\n"); + putstr(sc,prompt); + } + + /* Set up another iteration of REPL */ + sc->nesting=0; + sc->save_inport=sc->inport; + sc->inport = sc->loadport; + s_save(sc,OP_T0LVL, sc->NIL, sc->NIL); + s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL); + s_save(sc,OP_T1LVL, sc->NIL, sc->NIL); + s_goto(sc,OP_READ_INTERNAL); + + case OP_T1LVL: /* top level */ + sc->code = sc->value; + sc->inport=sc->save_inport; + s_goto(sc,OP_EVAL); + + case OP_READ_INTERNAL: /* internal read */ + sc->tok = token(sc); + if(sc->tok==TOK_EOF) + { s_return(sc,sc->EOF_OBJ); } + s_goto(sc,OP_RDSEXPR); + + case OP_GENSYM: + s_return(sc, gensym(sc)); + + case OP_VALUEPRINT: /* print evaluation result */ + /* OP_VALUEPRINT is always pushed, because when changing from + non-interactive to interactive mode, it needs to be + already on the stack */ + if(sc->tracing) { + putstr(sc,"\nGives: "); + } + if(file_interactive(sc) || sc->print_output) { + sc->print_flag = 1; + sc->args = sc->value; + s_goto(sc,OP_P0LIST); + } else { + s_return(sc,sc->value); + } + + case OP_EVAL: /* main part of evaluation */ +#if USE_TRACING + if(sc->tracing) { + /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/ + s_save(sc,OP_REAL_EVAL,sc->args,sc->code); + sc->args=sc->code; + putstr(sc,"\nEval: "); + s_goto(sc,OP_P0LIST); + } + /* fall through */ + case OP_REAL_EVAL: +#endif + if (is_symbol(sc->code)) { /* symbol */ + x=find_slot_in_env(sc,sc->envir,sc->code,1); + if (x != sc->NIL) { + s_return(sc,slot_value_in_env(x)); + } else { + Error_1(sc,"eval: unbound variable:", sc->code); + } + } else if (is_pair(sc->code)) { + if (is_syntax(x = car(sc->code))) { /* SYNTAX */ + sc->code = cdr(sc->code); + s_goto(sc,syntaxnum(x)); + } else {/* first, eval top element and eval arguments */ + s_save(sc,OP_E0ARGS, sc->NIL, sc->code); + /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/ + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + } + } else { + s_return(sc,sc->code); + } + + case OP_E0ARGS: /* eval arguments */ + if (is_macro(sc->value)) { /* macro expansion */ + s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL); + sc->args = cons(sc,sc->code, sc->NIL); + sc->code = sc->value; + s_goto(sc,OP_APPLY); + } else { + sc->code = cdr(sc->code); + s_goto(sc,OP_E1ARGS); + } + + case OP_E1ARGS: /* eval arguments */ + sc->args = cons(sc, sc->value, sc->args); + if (is_pair(sc->code)) { /* continue */ + s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code)); + sc->code = car(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->args = reverse_in_place(sc, sc->NIL, sc->args); + sc->code = car(sc->args); + sc->args = cdr(sc->args); + s_goto(sc,OP_APPLY); + } + +#if USE_TRACING + case OP_TRACING: { + int tr=sc->tracing; + sc->tracing=ivalue(car(sc->args)); + s_return(sc,mk_integer(sc,tr)); + } +#endif + + case OP_APPLY: /* apply 'code' to 'args' */ +#if USE_TRACING + if(sc->tracing) { + s_save(sc,OP_REAL_APPLY,sc->args,sc->code); + sc->print_flag = 1; + /* sc->args=cons(sc,sc->code,sc->args);*/ + putstr(sc,"\nApply to: "); + s_goto(sc,OP_P0LIST); + } + /* fall through */ + case OP_REAL_APPLY: +#endif + if (is_proc(sc->code)) { + s_goto(sc,procnum(sc->code)); /* PROCEDURE */ + } else if (is_foreign(sc->code)) + { + /* Keep nested calls from GC'ing the arglist */ + push_recent_alloc(sc,sc->args,sc->NIL); + sc->foreign_error = sc->NIL; + x=sc->code->_object._ff(sc,sc->args); + if (sc->foreign_error == sc->NIL) { + s_return(sc,x); + } else { + x = sc->foreign_error; + sc->foreign_error = sc->NIL; + Error_1 (sc, string_value (car (x)), cdr (x)); + } + } else if (is_closure(sc->code) || is_macro(sc->code) + || is_promise(sc->code)) { /* CLOSURE */ + /* Should not accept promise */ + /* make environment */ + new_frame_in_env(sc, closure_env(sc->code)); + for (x = car(closure_code(sc->code)), y = sc->args; + is_pair(x); x = cdr(x), y = cdr(y)) { + if (y == sc->NIL) { + Error_0(sc,"not enough arguments"); + } else { + new_slot_in_env(sc, car(x), car(y)); + } + } + if (x == sc->NIL) { + /*-- + * if (y != sc->NIL) { + * Error_0(sc,"too many arguments"); + * } + */ + } else if (is_symbol(x)) + new_slot_in_env(sc, x, y); + else { + Error_1(sc,"syntax error in closure: not a symbol:", x); + } + sc->code = cdr(closure_code(sc->code)); + sc->args = sc->NIL; + s_goto(sc,OP_BEGIN); + } else if (is_continuation(sc->code)) { /* CONTINUATION */ + sc->dump = cont_dump(sc->code); + s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL); + } else { + Error_0(sc,"illegal function"); + } + + case OP_DOMACRO: /* do macro */ + sc->code = sc->value; + s_goto(sc,OP_EVAL); + +#if 1 + case OP_LAMBDA: /* lambda */ + /* If the hook is defined, apply it to sc->code, otherwise + set sc->value fall thru */ + { + pointer f=find_slot_in_env(sc,sc->envir,sc->COMPILE_HOOK,1); + if(f==sc->NIL) { + sc->value = sc->code; + /* Fallthru */ + } else { + s_save(sc,OP_LAMBDA1,sc->args,sc->code); + sc->args=cons(sc,sc->code,sc->NIL); + sc->code=slot_value_in_env(f); + s_goto(sc,OP_APPLY); + } + } + + case OP_LAMBDA1: + s_return(sc,mk_closure(sc, sc->value, sc->envir)); + +#else + case OP_LAMBDA: /* lambda */ + s_return(sc,mk_closure(sc, sc->code, sc->envir)); + +#endif + + case OP_MKCLOSURE: /* make-closure */ + x=car(sc->args); + if(car(x)==sc->LAMBDA) { + x=cdr(x); + } + if(cdr(sc->args)==sc->NIL) { + y=sc->envir; + } else { + y=cadr(sc->args); + } + s_return(sc,mk_closure(sc, x, y)); + + case OP_QUOTE: /* quote */ + s_return(sc,car(sc->code)); + + case OP_DEF0: /* define */ + if(is_immutable(car(sc->code))) + Error_1(sc,"define: unable to alter immutable", car(sc->code)); + + if (is_pair(car(sc->code))) { + x = caar(sc->code); + sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code))); + } else { + x = car(sc->code); + sc->code = cadr(sc->code); + } + if (!is_symbol(x)) { + Error_0(sc,"variable is not a symbol"); + } + s_save(sc,OP_DEF1, sc->NIL, x); + s_goto(sc,OP_EVAL); + + case OP_DEF1: /* define */ + x=find_slot_in_env(sc,sc->envir,sc->code,0); + if (x != sc->NIL) { + set_slot_in_env(sc, x, sc->value); + } else { + new_slot_in_env(sc, sc->code, sc->value); + } + s_return(sc,sc->code); + + + case OP_DEFP: /* defined? */ + x=sc->envir; + if(cdr(sc->args)!=sc->NIL) { + x=cadr(sc->args); + } + s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL); + + case OP_SET0: /* set! */ + if(is_immutable(car(sc->code))) + Error_1(sc,"set!: unable to alter immutable variable",car(sc->code)); + s_save(sc,OP_SET1, sc->NIL, car(sc->code)); + sc->code = cadr(sc->code); + s_goto(sc,OP_EVAL); + + case OP_SET1: /* set! */ + y=find_slot_in_env(sc,sc->envir,sc->code,1); + if (y != sc->NIL) { + set_slot_in_env(sc, y, sc->value); + s_return(sc,sc->value); + } else { + Error_1(sc,"set!: unbound variable:", sc->code); + } + + case OP_BEGIN: /* begin */ + if (!is_pair(sc->code)) { + s_return(sc,sc->code); + } + if (cdr(sc->code) != sc->NIL) { + s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code)); + } + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_IF0: /* if */ + s_save(sc,OP_IF1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_IF1: /* if */ + if (is_true(sc->value)) + sc->code = car(sc->code); + else + sc->code = cadr(sc->code); /* (if #f 1) ==> () because + * car(sc->NIL) = sc->NIL */ + s_goto(sc,OP_EVAL); + + case OP_LET0: /* let */ + sc->args = sc->NIL; + sc->value = sc->code; + sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code); + s_goto(sc,OP_LET1); + + case OP_LET1: /* let (calculate parameters) */ + sc->args = cons(sc, sc->value, sc->args); + if (is_pair(sc->code)) { /* continue */ + if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) { + Error_1(sc, "Bad syntax of binding spec in let :", car(sc->code)); + } + s_save(sc,OP_LET1, sc->args, cdr(sc->code)); + sc->code = cadar(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->args = reverse_in_place(sc, sc->NIL, sc->args); + sc->code = car(sc->args); + sc->args = cdr(sc->args); + s_goto(sc,OP_LET2); + } + + case OP_LET2: /* let */ + new_frame_in_env(sc, sc->envir); + for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args; + y != sc->NIL; x = cdr(x), y = cdr(y)) { + new_slot_in_env(sc, caar(x), car(y)); + } + if (is_symbol(car(sc->code))) { /* named let */ + for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) { + if (!is_pair(x)) + Error_1(sc, "Bad syntax of binding in let :", x); + if (!is_list(sc, car(x))) + Error_1(sc, "Bad syntax of binding in let :", car(x)); + sc->args = cons(sc, caar(x), sc->args); + } + x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir); + new_slot_in_env(sc, car(sc->code), x); + sc->code = cddr(sc->code); + sc->args = sc->NIL; + } else { + sc->code = cdr(sc->code); + sc->args = sc->NIL; + } + s_goto(sc,OP_BEGIN); + + case OP_LET0AST: /* let* */ + if (car(sc->code) == sc->NIL) { + new_frame_in_env(sc, sc->envir); + sc->code = cdr(sc->code); + s_goto(sc,OP_BEGIN); + } + if(!is_pair(car(sc->code)) || !is_pair(caar(sc->code)) || !is_pair(cdaar(sc->code))) { + Error_1(sc,"Bad syntax of binding spec in let* :",car(sc->code)); + } + s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code)); + sc->code = cadaar(sc->code); + s_goto(sc,OP_EVAL); + + case OP_LET1AST: /* let* (make new frame) */ + new_frame_in_env(sc, sc->envir); + s_goto(sc,OP_LET2AST); + + case OP_LET2AST: /* let* (calculate parameters) */ + new_slot_in_env(sc, caar(sc->code), sc->value); + sc->code = cdr(sc->code); + if (is_pair(sc->code)) { /* continue */ + s_save(sc,OP_LET2AST, sc->args, sc->code); + sc->code = cadar(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->code = sc->args; + sc->args = sc->NIL; + s_goto(sc,OP_BEGIN); + } + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_1(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + + switch (op) { + case OP_LET0REC: /* letrec */ + new_frame_in_env(sc, sc->envir); + sc->args = sc->NIL; + sc->value = sc->code; + sc->code = car(sc->code); + s_goto(sc,OP_LET1REC); + + case OP_LET1REC: /* letrec (calculate parameters) */ + sc->args = cons(sc, sc->value, sc->args); + if (is_pair(sc->code)) { /* continue */ + if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) { + Error_1(sc,"Bad syntax of binding spec in letrec :",car(sc->code)); + } + s_save(sc,OP_LET1REC, sc->args, cdr(sc->code)); + sc->code = cadar(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->args = reverse_in_place(sc, sc->NIL, sc->args); + sc->code = car(sc->args); + sc->args = cdr(sc->args); + s_goto(sc,OP_LET2REC); + } + + case OP_LET2REC: /* letrec */ + for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) { + new_slot_in_env(sc, caar(x), car(y)); + } + sc->code = cdr(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_BEGIN); + + case OP_COND0: /* cond */ + if (!is_pair(sc->code)) { + Error_0(sc,"syntax error in cond"); + } + s_save(sc,OP_COND1, sc->NIL, sc->code); + sc->code = caar(sc->code); + s_goto(sc,OP_EVAL); + + case OP_COND1: /* cond */ + if (is_true(sc->value)) { + if ((sc->code = cdar(sc->code)) == sc->NIL) { + s_return(sc,sc->value); + } + if(!sc->code) { + Error_0(sc,"syntax error in cond"); + } + if(car(sc->code)==sc->FEED_TO) { + if(!is_pair(cdr(sc->code))) { + Error_0(sc,"syntax error in cond"); + } + x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)); + sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL)); + s_goto(sc,OP_EVAL); + } + s_goto(sc,OP_BEGIN); + } else { + if ((sc->code = cdr(sc->code)) == sc->NIL) { + s_return(sc,sc->NIL); + } else { + s_save(sc,OP_COND1, sc->NIL, sc->code); + sc->code = caar(sc->code); + s_goto(sc,OP_EVAL); + } + } + + case OP_DELAY: /* delay */ + x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir); + typeflag(x)=T_PROMISE; + s_return(sc,x); + + case OP_AND0: /* and */ + if (sc->code == sc->NIL) { + s_return(sc,sc->T); + } + s_save(sc,OP_AND1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_AND1: /* and */ + if (is_false(sc->value)) { + s_return(sc,sc->value); + } else if (sc->code == sc->NIL) { + s_return(sc,sc->value); + } else { + s_save(sc,OP_AND1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + } + + case OP_OR0: /* or */ + if (sc->code == sc->NIL) { + s_return(sc,sc->F); + } + s_save(sc,OP_OR1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_OR1: /* or */ + if (is_true(sc->value)) { + s_return(sc,sc->value); + } else if (sc->code == sc->NIL) { + s_return(sc,sc->value); + } else { + s_save(sc,OP_OR1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + } + + case OP_C0STREAM: /* cons-stream */ + s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_C1STREAM: /* cons-stream */ + sc->args = sc->value; /* save sc->value to register sc->args for gc */ + x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir); + typeflag(x)=T_PROMISE; + s_return(sc,cons(sc, sc->args, x)); + + case OP_MACRO0: /* macro */ + if (is_pair(car(sc->code))) { + x = caar(sc->code); + sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code))); + } else { + x = car(sc->code); + sc->code = cadr(sc->code); + } + if (!is_symbol(x)) { + Error_0(sc,"variable is not a symbol"); + } + s_save(sc,OP_MACRO1, sc->NIL, x); + s_goto(sc,OP_EVAL); + + case OP_MACRO1: /* macro */ + typeflag(sc->value) = T_MACRO; + x = find_slot_in_env(sc, sc->envir, sc->code, 0); + if (x != sc->NIL) { + set_slot_in_env(sc, x, sc->value); + } else { + new_slot_in_env(sc, sc->code, sc->value); + } + s_return(sc,sc->code); + + case OP_CASE0: /* case */ + s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_CASE1: /* case */ + for (x = sc->code; x != sc->NIL; x = cdr(x)) { + if (!is_pair(y = caar(x))) { + break; + } + for ( ; y != sc->NIL; y = cdr(y)) { + if (eqv(car(y), sc->value)) { + break; + } + } + if (y != sc->NIL) { + break; + } + } + if (x != sc->NIL) { + if (is_pair(caar(x))) { + sc->code = cdar(x); + s_goto(sc,OP_BEGIN); + } else {/* else */ + s_save(sc,OP_CASE2, sc->NIL, cdar(x)); + sc->code = caar(x); + s_goto(sc,OP_EVAL); + } + } else { + s_return(sc,sc->NIL); + } + + case OP_CASE2: /* case */ + if (is_true(sc->value)) { + s_goto(sc,OP_BEGIN); + } else { + s_return(sc,sc->NIL); + } + + case OP_PAPPLY: /* apply */ + sc->code = car(sc->args); + sc->args = list_star(sc,cdr(sc->args)); + /*sc->args = cadr(sc->args);*/ + s_goto(sc,OP_APPLY); + + case OP_PEVAL: /* eval */ + if(cdr(sc->args)!=sc->NIL) { + sc->envir=cadr(sc->args); + } + sc->code = car(sc->args); + s_goto(sc,OP_EVAL); + + case OP_CONTINUATION: /* call-with-current-continuation */ + sc->code = car(sc->args); + sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL); + s_goto(sc,OP_APPLY); + + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_2(scheme *sc, enum scheme_opcodes op) { + pointer x; + num v; +#if USE_MATH + double dd; +#endif + + switch (op) { +#if USE_MATH + case OP_INEX2EX: /* inexact->exact */ + x=car(sc->args); + if(num_is_integer(x)) { + s_return(sc,x); + } else if(modf(rvalue_unchecked(x),&dd)==0.0) { + s_return(sc,mk_integer(sc,ivalue(x))); + } else { + Error_1(sc,"inexact->exact: not integral:",x); + } + + case OP_EXP: + x=car(sc->args); + s_return(sc, mk_real(sc, exp(rvalue(x)))); + + case OP_LOG: + x=car(sc->args); + s_return(sc, mk_real(sc, log(rvalue(x)))); + + case OP_SIN: + x=car(sc->args); + s_return(sc, mk_real(sc, sin(rvalue(x)))); + + case OP_COS: + x=car(sc->args); + s_return(sc, mk_real(sc, cos(rvalue(x)))); + + case OP_TAN: + x=car(sc->args); + s_return(sc, mk_real(sc, tan(rvalue(x)))); + + case OP_ASIN: + x=car(sc->args); + s_return(sc, mk_real(sc, asin(rvalue(x)))); + + case OP_ACOS: + x=car(sc->args); + s_return(sc, mk_real(sc, acos(rvalue(x)))); + + case OP_ATAN: + x=car(sc->args); + if(cdr(sc->args)==sc->NIL) { + s_return(sc, mk_real(sc, atan(rvalue(x)))); + } else { + pointer y=cadr(sc->args); + s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y)))); + } + + case OP_SQRT: + x=car(sc->args); + s_return(sc, mk_real(sc, sqrt(rvalue(x)))); + + case OP_EXPT: { + double result; + int real_result=1; + pointer y=cadr(sc->args); + x=car(sc->args); + if (num_is_integer(x) && num_is_integer(y)) + real_result=0; + /* This 'if' is an R5RS compatibility fix. */ + /* NOTE: Remove this 'if' fix for R6RS. */ + if (rvalue(x) == 0 && rvalue(y) < 0) { + result = 0.0; + } else { + result = pow(rvalue(x),rvalue(y)); + } + /* Before returning integer result make sure we can. */ + /* If the test fails, result is too big for integer. */ + if (!real_result) + { + long result_as_long = (long)result; + if (result != (double)result_as_long) + real_result = 1; + } + if (real_result) { + s_return(sc, mk_real(sc, result)); + } else { + s_return(sc, mk_integer(sc, result)); + } + } + + case OP_FLOOR: + x=car(sc->args); + s_return(sc, mk_real(sc, floor(rvalue(x)))); + + case OP_CEILING: + x=car(sc->args); + s_return(sc, mk_real(sc, ceil(rvalue(x)))); + + case OP_TRUNCATE : { + double rvalue_of_x ; + x=car(sc->args); + rvalue_of_x = rvalue(x) ; + if (rvalue_of_x > 0) { + s_return(sc, mk_real(sc, floor(rvalue_of_x))); + } else { + s_return(sc, mk_real(sc, ceil(rvalue_of_x))); + } + } + + case OP_ROUND: + x=car(sc->args); + if (num_is_integer(x)) + s_return(sc, x); + s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x)))); +#endif + + case OP_ADD: /* + */ + v=num_zero; + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + v=num_add(v,nvalue(car(x))); + } + s_return(sc,mk_number(sc, v)); + + case OP_MUL: /* * */ + v=num_one; + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + v=num_mul(v,nvalue(car(x))); + } + s_return(sc,mk_number(sc, v)); + + case OP_SUB: /* - */ + if(cdr(sc->args)==sc->NIL) { + x=sc->args; + v=num_zero; + } else { + x = cdr(sc->args); + v = nvalue(car(sc->args)); + } + for (; x != sc->NIL; x = cdr(x)) { + v=num_sub(v,nvalue(car(x))); + } + s_return(sc,mk_number(sc, v)); + + case OP_DIV: /* / */ + if(cdr(sc->args)==sc->NIL) { + x=sc->args; + v=num_one; + } else { + x = cdr(sc->args); + v = nvalue(car(sc->args)); + } + for (; x != sc->NIL; x = cdr(x)) { + if (!is_zero_double(rvalue(car(x)))) + v=num_div(v,nvalue(car(x))); + else { + Error_0(sc,"/: division by zero"); + } + } + s_return(sc,mk_number(sc, v)); + + case OP_INTDIV: /* quotient */ + if(cdr(sc->args)==sc->NIL) { + x=sc->args; + v=num_one; + } else { + x = cdr(sc->args); + v = nvalue(car(sc->args)); + } + for (; x != sc->NIL; x = cdr(x)) { + if (ivalue(car(x)) != 0) + v=num_intdiv(v,nvalue(car(x))); + else { + Error_0(sc,"quotient: division by zero"); + } + } + s_return(sc,mk_number(sc, v)); + + case OP_REM: /* remainder */ + v = nvalue(car(sc->args)); + if (ivalue(cadr(sc->args)) != 0) + v=num_rem(v,nvalue(cadr(sc->args))); + else { + Error_0(sc,"remainder: division by zero"); + } + s_return(sc,mk_number(sc, v)); + + case OP_MOD: /* modulo */ + v = nvalue(car(sc->args)); + if (ivalue(cadr(sc->args)) != 0) + v=num_mod(v,nvalue(cadr(sc->args))); + else { + Error_0(sc,"modulo: division by zero"); + } + s_return(sc,mk_number(sc, v)); + + case OP_CAR: /* car */ + s_return(sc,caar(sc->args)); + + case OP_CDR: /* cdr */ + s_return(sc,cdar(sc->args)); + + case OP_CONS: /* cons */ + cdr(sc->args) = cadr(sc->args); + s_return(sc,sc->args); + + case OP_SETCAR: /* set-car! */ + if(!is_immutable(car(sc->args))) { + caar(sc->args) = cadr(sc->args); + s_return(sc,car(sc->args)); + } else { + Error_0(sc,"set-car!: unable to alter immutable pair"); + } + + case OP_SETCDR: /* set-cdr! */ + if(!is_immutable(car(sc->args))) { + cdar(sc->args) = cadr(sc->args); + s_return(sc,car(sc->args)); + } else { + Error_0(sc,"set-cdr!: unable to alter immutable pair"); + } + + case OP_CHAR2INT: { /* char->integer */ + gunichar c; + c=ivalue(car(sc->args)); + s_return(sc,mk_integer(sc,c)); + } + + case OP_INT2CHAR: { /* integer->char */ + gunichar c; + c=(gunichar)ivalue(car(sc->args)); + s_return(sc,mk_character(sc,c)); + } + + case OP_CHARUPCASE: { + gunichar c; + c=(gunichar)ivalue(car(sc->args)); + c=g_unichar_toupper(c); + s_return(sc,mk_character(sc,c)); + } + + case OP_CHARDNCASE: { + gunichar c; + c=(gunichar)ivalue(car(sc->args)); + c=g_unichar_tolower(c); + s_return(sc,mk_character(sc,c)); + } + + case OP_STR2SYM: /* string->symbol */ + s_return(sc,mk_symbol(sc,strvalue(car(sc->args)))); + + case OP_STR2ATOM: /* string->atom */ { + char *s=strvalue(car(sc->args)); + long pf = 0; + if(cdr(sc->args)!=sc->NIL) { + /* we know cadr(sc->args) is a natural number */ + /* see if it is 2, 8, 10, or 16, or error */ + pf = ivalue_unchecked(cadr(sc->args)); + if(pf == 16 || pf == 10 || pf == 8 || pf == 2) { + /* base is OK */ + } + else { + pf = -1; + } + } + if (pf < 0) { + Error_1(sc, "string->atom: bad base:", cadr(sc->args)); + } else if(*s=='#') /* no use of base! */ { + s_return(sc, mk_sharp_const(sc, s+1)); + } else { + if (pf == 0 || pf == 10) { + s_return(sc, mk_atom(sc, s)); + } + else { + char *ep; + long iv = strtol(s,&ep,(int )pf); + if (*ep == 0) { + s_return(sc, mk_integer(sc, iv)); + } + else { + s_return(sc, sc->F); + } + } + } + } + + case OP_SYM2STR: /* symbol->string */ + x=mk_string(sc,symname(car(sc->args))); + setimmutable(x); + s_return(sc,x); + + case OP_ATOM2STR: /* atom->string */ { + long pf = 0; + x=car(sc->args); + if(cdr(sc->args)!=sc->NIL) { + /* we know cadr(sc->args) is a natural number */ + /* see if it is 2, 8, 10, or 16, or error */ + pf = ivalue_unchecked(cadr(sc->args)); + if(is_number(x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2)) { + /* base is OK */ + } + else { + pf = -1; + } + } + if (pf < 0) { + Error_1(sc, "atom->string: bad base:", cadr(sc->args)); + } else if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) { + char *p; + int len; + atom2str(sc,x,(int )pf,&p,&len); + s_return(sc,mk_counted_string(sc,p,len)); + } else { + Error_1(sc, "atom->string: not an atom:", x); + } + } + + case OP_MKSTRING: { /* make-string */ + gunichar fill=' '; + int len; + + len=ivalue(car(sc->args)); + + if(cdr(sc->args)!=sc->NIL) { + fill=charvalue(cadr(sc->args)); + } + s_return(sc,mk_empty_string(sc,len,fill)); + } + + case OP_STRLEN: /* string-length */ + s_return(sc,mk_integer(sc,g_utf8_strlen(strvalue(car(sc->args)), -1))); + + case OP_STRREF: { /* string-ref */ + char *str; + int index; + + str=strvalue(car(sc->args)); + + index=ivalue(cadr(sc->args)); + + if(index>=g_utf8_strlen(strvalue(car(sc->args)), -1)) { + Error_1(sc,"string-ref: out of bounds:",cadr(sc->args)); + } + + str = g_utf8_offset_to_pointer(str, (long)index); + s_return(sc,mk_character(sc, g_utf8_get_char(str))); + } + + case OP_STRSET: { /* string-set! */ + pointer a; + char *str; + int index; + gunichar c; + char utf8[7]; + int utf8_len; + int newlen; + char *p1, *p2; + int p1_len; + int p2_len; + char *newstr; + + a=car(sc->args); + if(is_immutable(a)) { + Error_1(sc,"string-set!: unable to alter immutable string:",a); + } + + str=strvalue(a); + index=ivalue(cadr(sc->args)); + if(index>=g_utf8_strlen(str, -1)) { + Error_1(sc,"string-set!: out of bounds:",cadr(sc->args)); + } + + c=charvalue(caddr(sc->args)); + utf8_len = g_unichar_to_utf8(c, utf8); + + p1 = g_utf8_offset_to_pointer(str, (long)index); + p2 = g_utf8_offset_to_pointer(str, (long)index+1); + p1_len = p1-str; + p2_len = strlen(p2); + + newlen = p1_len+utf8_len+p2_len; + newstr = (char *)sc->malloc(newlen+1); + if (newstr == NULL) { + sc->no_memory=1; + Error_1(sc,"string-set!: No memory to alter string:",car(sc->args)); + } + + if (p1_len > 0) + memcpy(newstr, str, p1_len); + memcpy(newstr+p1_len, utf8, utf8_len); + if (p2_len > 0) + memcpy(newstr+p1_len+utf8_len, p2, p2_len); + newstr[newlen] = '\0'; + + free(strvalue(a)); + strvalue(a)=newstr; + strlength(a)=g_utf8_strlen(newstr, -1); + + s_return(sc,a); + } + + case OP_STRAPPEND: { /* string-append */ + /* in 1.29 string-append was in Scheme in init.scm but was too slow */ + int len = 0; + pointer car_x; + char *newstr; + char *pos; + char *end; + + /* compute needed length for new string */ + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + car_x = car(x); + end = g_utf8_offset_to_pointer(strvalue(car_x), (long)strlength(car_x)); + len += end - strvalue(car_x); + } + + newstr = (char *)sc->malloc(len+1); + if (newstr == NULL) { + sc->no_memory=1; + Error_1(sc,"string-set!: No memory to append strings:",car(sc->args)); + } + + /* store the contents of the argument strings into the new string */ + pos = newstr; + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + car_x = car(x); + end = g_utf8_offset_to_pointer(strvalue(car_x), (long)strlength(car_x)); + len = end - strvalue(car_x); + memcpy(pos, strvalue(car_x), len); + pos += len; + } + *pos = '\0'; + + car_x = mk_string(sc, newstr); + g_free(newstr); + + s_return(sc, car_x); + } + + case OP_SUBSTR: { /* substring */ + char *str; + char *beg; + char *end; + int index0; + int index1; + int len; + pointer x; + + str=strvalue(car(sc->args)); + + index0=ivalue(cadr(sc->args)); + + if(index0>g_utf8_strlen(str, -1)) { + Error_1(sc,"substring: start out of bounds:",cadr(sc->args)); + } + + if(cddr(sc->args)!=sc->NIL) { + index1=ivalue(caddr(sc->args)); + if(index1>g_utf8_strlen(str, -1) || index1<index0) { + Error_1(sc,"substring: end out of bounds:",caddr(sc->args)); + } + } else { + index1=g_utf8_strlen(str, -1); + } + + /* store the contents of the argument strings into the new string */ + beg = g_utf8_offset_to_pointer(str, (long)index0); + end = g_utf8_offset_to_pointer(str, (long)index1); + len=end-beg; + + str = (char *)sc->malloc(len+1); + if (str == NULL) { + sc->no_memory=1; + Error_1(sc,"string-set!: No memory to extract substring:",car(sc->args)); + } + + memcpy(str, beg, len); + str[len] = '\0'; + + x = mk_string(sc, str); + g_free(str); + + s_return(sc,x); + } + + case OP_VECTOR: { /* vector */ + int i; + pointer vec; + int len=list_length(sc,sc->args); + if(len<0) { + Error_1(sc,"vector: not a proper list:",sc->args); + } + vec=mk_vector(sc,len); + if(sc->no_memory) { s_return(sc, sc->sink); } + for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) { + set_vector_elem(vec,i,car(x)); + } + s_return(sc,vec); + } + + case OP_MKVECTOR: { /* make-vector */ + pointer fill=sc->NIL; + int len; + pointer vec; + + len=ivalue(car(sc->args)); + + if(cdr(sc->args)!=sc->NIL) { + fill=cadr(sc->args); + } + vec=mk_vector(sc,len); + if(sc->no_memory) { s_return(sc, sc->sink); } + if(fill!=sc->NIL) { + fill_vector(vec,fill); + } + s_return(sc,vec); + } + + case OP_VECLEN: /* vector-length */ + s_return(sc,mk_integer(sc,ivalue(car(sc->args)))); + + case OP_VECREF: { /* vector-ref */ + int index; + + index=ivalue(cadr(sc->args)); + + if(index>=ivalue(car(sc->args))) { + Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args)); + } + + s_return(sc,vector_elem(car(sc->args),index)); + } + + case OP_VECSET: { /* vector-set! */ + int index; + + if(is_immutable(car(sc->args))) { + Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args)); + } + + index=ivalue(cadr(sc->args)); + if(index>=ivalue(car(sc->args))) { + Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args)); + } + + set_vector_elem(car(sc->args),index,caddr(sc->args)); + s_return(sc,car(sc->args)); + } + + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static int is_list(scheme *sc, pointer a) +{ return list_length(sc,a) >= 0; } + +/* Result is: + proper list: length + circular list: -1 + not even a pair: -2 + dotted list: -2 minus length before dot +*/ +int list_length(scheme *sc, pointer p) { + int i=0; + pointer slow, fast; + + slow = fast = p; + while (1) + { + if (fast == sc->NIL) + return i; + if (!is_pair(fast)) + return -2 - i; + fast = cdr(fast); + ++i; + if (fast == sc->NIL) + return i; + if (!is_pair(fast)) + return -2 - i; + ++i; + fast = cdr(fast); + + /* Safe because we would have already returned if `fast' + encountered a non-pair. */ + slow = cdr(slow); + if (fast == slow) + { + /* the fast pointer has looped back around and caught up + with the slow pointer, hence the structure is circular, + not of finite length, and therefore not a list */ + return -1; + } + } +} + +static pointer opexe_3(scheme *sc, enum scheme_opcodes op) { + pointer x; + num v; + int (*comp_func)(num,num)=0; + + switch (op) { + case OP_NOT: /* not */ + s_retbool(is_false(car(sc->args))); + case OP_BOOLP: /* boolean? */ + s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T); + case OP_EOFOBJP: /* boolean? */ + s_retbool(car(sc->args) == sc->EOF_OBJ); + case OP_NULLP: /* null? */ + s_retbool(car(sc->args) == sc->NIL); + case OP_NUMEQ: /* = */ + case OP_LESS: /* < */ + case OP_GRE: /* > */ + case OP_LEQ: /* <= */ + case OP_GEQ: /* >= */ + switch(op) { + case OP_NUMEQ: comp_func=num_eq; break; + case OP_LESS: comp_func=num_lt; break; + case OP_GRE: comp_func=num_gt; break; + case OP_LEQ: comp_func=num_le; break; + case OP_GEQ: comp_func=num_ge; break; + default: break; /* Quiet the compiler */ + } + x=sc->args; + v=nvalue(car(x)); + x=cdr(x); + + for (; x != sc->NIL; x = cdr(x)) { + if(!comp_func(v,nvalue(car(x)))) { + s_retbool(0); + } + v=nvalue(car(x)); + } + s_retbool(1); + case OP_SYMBOLP: /* symbol? */ + s_retbool(is_symbol(car(sc->args))); + case OP_NUMBERP: /* number? */ + s_retbool(is_number(car(sc->args))); + case OP_STRINGP: /* string? */ + s_retbool(is_string(car(sc->args))); + case OP_INTEGERP: /* integer? */ + s_retbool(is_integer(car(sc->args))); + case OP_REALP: /* real? */ + s_retbool(is_number(car(sc->args))); /* All numbers are real */ + case OP_CHARP: /* char? */ + s_retbool(is_character(car(sc->args))); +#if USE_CHAR_CLASSIFIERS + case OP_CHARAP: /* char-alphabetic? */ + s_retbool(Cisalpha(ivalue(car(sc->args)))); + case OP_CHARNP: /* char-numeric? */ + s_retbool(Cisdigit(ivalue(car(sc->args)))); + case OP_CHARWP: /* char-whitespace? */ + s_retbool(Cisspace(ivalue(car(sc->args)))); + case OP_CHARUP: /* char-upper-case? */ + s_retbool(Cisupper(ivalue(car(sc->args)))); + case OP_CHARLP: /* char-lower-case? */ + s_retbool(Cislower(ivalue(car(sc->args)))); +#endif + case OP_PORTP: /* port? */ + s_retbool(is_port(car(sc->args))); + case OP_INPORTP: /* input-port? */ + s_retbool(is_inport(car(sc->args))); + case OP_OUTPORTP: /* output-port? */ + s_retbool(is_outport(car(sc->args))); + case OP_PROCP: /* procedure? */ + /*-- + * continuation should be procedure by the example + * (call-with-current-continuation procedure?) ==> #t + * in R^3 report sec. 6.9 + */ + s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args)) + || is_continuation(car(sc->args)) || is_foreign(car(sc->args))); + case OP_PAIRP: /* pair? */ + s_retbool(is_pair(car(sc->args))); + case OP_LISTP: /* list? */ + s_retbool(list_length(sc,car(sc->args)) >= 0); + case OP_ENVP: /* environment? */ + s_retbool(is_environment(car(sc->args))); + case OP_VECTORP: /* vector? */ + s_retbool(is_vector(car(sc->args))); + case OP_EQ: /* eq? */ + s_retbool(car(sc->args) == cadr(sc->args)); + case OP_EQV: /* eqv? */ + s_retbool(eqv(car(sc->args), cadr(sc->args))); + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_4(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + + switch (op) { + case OP_FORCE: /* force */ + sc->code = car(sc->args); + if (is_promise(sc->code)) { + /* Should change type to closure here */ + s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_APPLY); + } else { + s_return(sc,sc->code); + } + + case OP_SAVE_FORCED: /* Save forced value replacing promise */ + memcpy(sc->code,sc->value,sizeof(struct cell)); + s_return(sc,sc->value); + + case OP_WRITE: /* write */ + case OP_DISPLAY: /* display */ + case OP_WRITE_CHAR: /* write-char */ + if(is_pair(cdr(sc->args))) { + if(cadr(sc->args)!=sc->outport) { + x=cons(sc,sc->outport,sc->NIL); + s_save(sc,OP_SET_OUTPORT, x, sc->NIL); + sc->outport=cadr(sc->args); + } + } + sc->args = car(sc->args); + if(op==OP_WRITE) { + sc->print_flag = 1; + } else { + sc->print_flag = 0; + } + s_goto(sc,OP_P0LIST); + + case OP_NEWLINE: /* newline */ + if(is_pair(sc->args)) { + if(car(sc->args)!=sc->outport) { + x=cons(sc,sc->outport,sc->NIL); + s_save(sc,OP_SET_OUTPORT, x, sc->NIL); + sc->outport=car(sc->args); + } + } + putstr(sc, "\n"); + s_return(sc,sc->T); + + case OP_ERR0: /* error */ + sc->retcode=-1; + if (!is_string(car(sc->args))) { + sc->args=cons(sc,mk_string(sc," -- "),sc->args); + setimmutable(car(sc->args)); + } + putstr(sc, "Error: "); + putstr(sc, strvalue(car(sc->args))); + sc->args = cdr(sc->args); + s_goto(sc,OP_ERR1); + + case OP_ERR1: /* error */ + putstr(sc, " "); + if (sc->args != sc->NIL) { + s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL); + sc->args = car(sc->args); + sc->print_flag = 1; + s_goto(sc,OP_P0LIST); + } else { + putstr(sc, "\n"); + if(sc->interactive_repl) { + s_goto(sc,OP_T0LVL); + } else { + return sc->NIL; + } + } + + case OP_REVERSE: /* reverse */ + s_return(sc,reverse(sc, car(sc->args))); + + case OP_LIST_STAR: /* list* */ + s_return(sc,list_star(sc,sc->args)); + + case OP_APPEND: /* append */ + x = sc->NIL; + y = sc->args; + if (y == x) { + s_return(sc, x); + } + + /* cdr() in the while condition is not a typo. If car() */ + /* is used (append '() 'a) will return the wrong result.*/ + while (cdr(y) != sc->NIL) { + x = revappend(sc, x, car(y)); + y = cdr(y); + if (x == sc->F) { + Error_0(sc, "non-list argument to append"); + } + } + + s_return(sc, reverse_in_place(sc, car(y), x)); + +#if USE_PLIST + case OP_PUT: /* put */ + if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) { + Error_0(sc,"illegal use of put"); + } + for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) { + if (caar(x) == y) { + break; + } + } + if (x != sc->NIL) + cdar(x) = caddr(sc->args); + else + symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)), + symprop(car(sc->args))); + s_return(sc,sc->T); + + case OP_GET: /* get */ + if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) { + Error_0(sc,"illegal use of get"); + } + for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) { + if (caar(x) == y) { + break; + } + } + if (x != sc->NIL) { + s_return(sc,cdar(x)); + } else { + s_return(sc,sc->NIL); + } +#endif /* USE_PLIST */ + case OP_QUIT: /* quit */ + if(is_pair(sc->args)) { + sc->retcode=ivalue(car(sc->args)); + } + return (sc->NIL); + + case OP_GC: /* gc */ + gc(sc, sc->NIL, sc->NIL); + s_return(sc,sc->T); + + case OP_GCVERB: /* gc-verbose */ + { int was = sc->gc_verbose; + + sc->gc_verbose = (car(sc->args) != sc->F); + s_retbool(was); + } + + case OP_NEWSEGMENT: /* new-segment */ + if (!is_pair(sc->args) || !is_number(car(sc->args))) { + Error_0(sc,"new-segment: argument must be a number"); + } + alloc_cellseg(sc, (int) ivalue(car(sc->args))); + s_return(sc,sc->T); + + case OP_OBLIST: /* oblist */ + s_return(sc, oblist_all_symbols(sc)); + + case OP_CURR_INPORT: /* current-input-port */ + s_return(sc,sc->inport); + + case OP_CURR_OUTPORT: /* current-output-port */ + s_return(sc,sc->outport); + + case OP_OPEN_INFILE: /* open-input-file */ + case OP_OPEN_OUTFILE: /* open-output-file */ + case OP_OPEN_INOUTFILE: /* open-input-output-file */ { + int prop=0; + pointer p; + switch(op) { + case OP_OPEN_INFILE: prop=port_input; break; + case OP_OPEN_OUTFILE: prop=port_output; break; + case OP_OPEN_INOUTFILE: prop=port_input|port_output; break; + default: break; /* Quiet the compiler */ + } + p=port_from_filename(sc,strvalue(car(sc->args)),prop); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + s_return(sc,p); + } + +#if USE_STRING_PORTS + case OP_OPEN_INSTRING: /* open-input-string */ + case OP_OPEN_INOUTSTRING: /* open-input-output-string */ { + int prop=0; + pointer p; + switch(op) { + case OP_OPEN_INSTRING: prop=port_input; break; + case OP_OPEN_INOUTSTRING: prop=port_input|port_output; break; + default: break; /* Quiet the compiler */ + } + p=port_from_string(sc, strvalue(car(sc->args)), + g_utf8_offset_to_pointer(strvalue(car(sc->args)), + strlength(car(sc->args))), prop); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + s_return(sc,p); + } + case OP_OPEN_OUTSTRING: /* open-output-string */ { + pointer p; + if(car(sc->args)==sc->NIL) { + p=port_from_scratch(sc); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + } else { + p=port_from_string(sc, strvalue(car(sc->args)), + strvalue(car(sc->args))+strlength(car(sc->args)), + port_output); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + } + s_return(sc,p); + } + case OP_GET_OUTSTRING: /* get-output-string */ { + port *p; + + if ((p=car(sc->args)->_object._port)->kind&port_string) { + off_t size; + char *str; + + size=p->rep.string.curr-p->rep.string.start+1; + str=sc->malloc(size); + if(str != NULL) { + pointer s; + + memcpy(str,p->rep.string.start,size-1); + str[size-1]='\0'; + s=mk_string(sc,str); + sc->free(str); + s_return(sc,s); + } + } + s_return(sc,sc->F); + } +#endif + + case OP_CLOSE_INPORT: /* close-input-port */ + port_close(sc,car(sc->args),port_input); + s_return(sc,sc->T); + + case OP_CLOSE_OUTPORT: /* close-output-port */ + port_close(sc,car(sc->args),port_output); + s_return(sc,sc->T); + + case OP_INT_ENV: /* interaction-environment */ + s_return(sc,sc->global_env); + + case OP_CURR_ENV: /* current-environment */ + s_return(sc,sc->envir); + + default: + sprintf(sc->strbuff, "%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_5(scheme *sc, enum scheme_opcodes op) { + pointer x; + char *trans_str; + + if(sc->nesting!=0) { + int n=sc->nesting; + sc->nesting=0; + sc->retcode=-1; + Error_1(sc,"unmatched parentheses:",mk_integer(sc,n)); + } + + switch (op) { + /* ========== reading part ========== */ + case OP_READ: + if(!is_pair(sc->args)) { + s_goto(sc,OP_READ_INTERNAL); + } + if(!is_inport(car(sc->args))) { + Error_1(sc,"read: not an input port:",car(sc->args)); + } + if(car(sc->args)==sc->inport) { + s_goto(sc,OP_READ_INTERNAL); + } + x=sc->inport; + sc->inport=car(sc->args); + x=cons(sc,x,sc->NIL); + s_save(sc,OP_SET_INPORT, x, sc->NIL); + s_goto(sc,OP_READ_INTERNAL); + + case OP_READ_CHAR: /* read-char */ + case OP_PEEK_CHAR: /* peek-char */ { + gunichar c; + if(is_pair(sc->args)) { + if(car(sc->args)!=sc->inport) { + x=sc->inport; + x=cons(sc,x,sc->NIL); + s_save(sc,OP_SET_INPORT, x, sc->NIL); + sc->inport=car(sc->args); + } + } + c=inchar(sc); + if(c==EOF) { + s_return(sc,sc->EOF_OBJ); + } + if(sc->op==OP_PEEK_CHAR) { + backchar(sc,c); + } + s_return(sc,mk_character(sc,c)); + } + + case OP_CHAR_READY: /* char-ready? */ { + pointer p=sc->inport; + int res; + if(is_pair(sc->args)) { + p=car(sc->args); + } + res=p->_object._port->kind&port_string; + s_retbool(res); + } + + case OP_SET_INPORT: /* set-input-port */ + sc->inport=car(sc->args); + s_return(sc,sc->value); + + case OP_SET_OUTPORT: /* set-output-port */ + sc->outport=car(sc->args); + s_return(sc,sc->value); + + case OP_RDSEXPR: + switch (sc->tok) { + case TOK_EOF: + s_return(sc,sc->EOF_OBJ); + /* NOTREACHED */ +/* + * Commented out because we now skip comments in the scanner + * + case TOK_COMMENT: { + gunichar c; + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + } +*/ + case TOK_VEC: + s_save(sc,OP_RDVEC,sc->NIL,sc->NIL); + /* fall through */ + case TOK_LPAREN: + sc->tok = token(sc); + if (sc->tok == TOK_RPAREN) { + s_return(sc,sc->NIL); + } else if (sc->tok == TOK_DOT) { + Error_0(sc,"syntax error: illegal dot expression"); + } else { + sc->nesting_stack[sc->file_i]++; + s_save(sc,OP_RDLIST, sc->NIL, sc->NIL); + s_goto(sc,OP_RDSEXPR); + } + case TOK_QUOTE: + s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + case TOK_BQUOTE: + sc->tok = token(sc); + if(sc->tok==TOK_VEC) { + s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL); + sc->tok=TOK_LPAREN; + s_goto(sc,OP_RDSEXPR); + } else { + s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL); + } + s_goto(sc,OP_RDSEXPR); + case TOK_COMMA: + s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + case TOK_ATMARK: + s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + case TOK_ATOM: + s_return(sc,mk_atom(sc, readstr_upto(sc, DELIMITERS))); + case TOK_DQUOTE: + x=readstrexp(sc); + if(x==sc->F) { + Error_0(sc,"Error reading string"); + } + setimmutable(x); + s_return(sc,x); + case TOK_USCORE: + x=readstrexp(sc); + if(x==sc->F) { + Error_0(sc,"Error reading string"); + } + trans_str = gettext (strvalue (x)); + if (trans_str != strvalue(x)) { + sc->free(strvalue(x)); + strlength(x) = g_utf8_strlen(trans_str, -1); + strvalue(x) = store_string(sc, strlength(x), trans_str, 0); + } + setimmutable(x); + s_return(sc,x); + case TOK_SHARP: { + pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1); + if(f==sc->NIL) { + Error_0(sc,"undefined sharp expression"); + } else { + sc->code=cons(sc,slot_value_in_env(f),sc->NIL); + s_goto(sc,OP_EVAL); + } + } + case TOK_SHARP_CONST: + if ((x = mk_sharp_const(sc, readstr_upto(sc, DELIMITERS))) == sc->NIL) { + Error_0(sc,"undefined sharp expression"); + } else { + s_return(sc,x); + } + default: + Error_1(sc, "syntax error: illegal token", mk_integer (sc, sc->tok)); + } + break; + + case OP_RDLIST: { + sc->args = cons(sc, sc->value, sc->args); + sc->tok = token(sc); +/* We now skip comments in the scanner + while (sc->tok == TOK_COMMENT) { + gunichar c; + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + sc->tok = token(sc); + } +*/ + if (sc->tok == TOK_EOF) + { s_return(sc,sc->EOF_OBJ); } + else if (sc->tok == TOK_RPAREN) { + gunichar c = inchar(sc); + if (c != '\n') + backchar(sc,c); +#if SHOW_ERROR_LINE + else if (sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line++; +#endif + sc->nesting_stack[sc->file_i]--; + s_return(sc,reverse_in_place(sc, sc->NIL, sc->args)); + } else if (sc->tok == TOK_DOT) { + s_save(sc,OP_RDDOT, sc->args, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + } else { + s_save(sc,OP_RDLIST, sc->args, sc->NIL); + s_goto(sc,OP_RDSEXPR); + } + } + + case OP_RDDOT: + if (token(sc) != TOK_RPAREN) { + Error_0(sc,"syntax error: illegal dot expression"); + } else { + sc->nesting_stack[sc->file_i]--; + s_return(sc,reverse_in_place(sc, sc->value, sc->args)); + } + + case OP_RDQUOTE: + s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL))); + + case OP_RDQQUOTE: + s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL))); + + case OP_RDQQUOTEVEC: + s_return(sc,cons(sc, mk_symbol(sc,"apply"), + cons(sc, mk_symbol(sc,"vector"), + cons(sc,cons(sc, sc->QQUOTE, + cons(sc,sc->value,sc->NIL)), + sc->NIL)))); + + case OP_RDUNQUOTE: + s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL))); + + case OP_RDUQTSP: + s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL))); + + case OP_RDVEC: + /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value); + s_goto(sc,OP_EVAL); Cannot be quoted*/ + /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value); + s_return(sc,x); Cannot be part of pairs*/ + /*sc->code=mk_proc(sc,OP_VECTOR); + sc->args=sc->value; + s_goto(sc,OP_APPLY);*/ + sc->args=sc->value; + s_goto(sc,OP_VECTOR); + + /* ========== printing part ========== */ + case OP_P0LIST: + if(is_vector(sc->args)) { + putstr(sc,"#("); + sc->args=cons(sc,sc->args,mk_integer(sc,0)); + s_goto(sc,OP_PVECFROM); + } else if(is_environment(sc->args)) { + putstr(sc,"#<ENVIRONMENT>"); + s_return(sc,sc->T); + } else if (!is_pair(sc->args)) { + printatom(sc, sc->args, sc->print_flag); + s_return(sc,sc->T); + } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) { + putstr(sc, "'"); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) { + putstr(sc, "`"); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) { + putstr(sc, ","); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) { + putstr(sc, ",@"); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else { + putstr(sc, "("); + s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL); + sc->args = car(sc->args); + s_goto(sc,OP_P0LIST); + } + + case OP_P1LIST: + if (is_pair(sc->args)) { + s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL); + putstr(sc, " "); + sc->args = car(sc->args); + s_goto(sc,OP_P0LIST); + } else if(is_vector(sc->args)) { + s_save(sc,OP_P1LIST,sc->NIL,sc->NIL); + putstr(sc, " . "); + s_goto(sc,OP_P0LIST); + } else { + if (sc->args != sc->NIL) { + putstr(sc, " . "); + printatom(sc, sc->args, sc->print_flag); + } + putstr(sc, ")"); + s_return(sc,sc->T); + } + case OP_PVECFROM: { + int i=ivalue_unchecked(cdr(sc->args)); + pointer vec=car(sc->args); + int len=ivalue_unchecked(vec); + if(i==len) { + putstr(sc,")"); + s_return(sc,sc->T); + } else { + pointer elem=vector_elem(vec,i); + ivalue_unchecked(cdr(sc->args))=i+1; + s_save(sc,OP_PVECFROM, sc->args, sc->NIL); + sc->args=elem; + if (i > 0) + putstr(sc," "); + s_goto(sc,OP_P0LIST); + } + } + + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + + } + return sc->T; +} + +static pointer opexe_6(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + long v; + + switch (op) { + case OP_LIST_LENGTH: /* length */ /* a.k */ + v=list_length(sc,car(sc->args)); + if(v<0) { + Error_1(sc,"length: not a list:",car(sc->args)); + } + s_return(sc,mk_integer(sc, v)); + + case OP_ASSQ: /* assq */ /* a.k */ + x = car(sc->args); + for (y = cadr(sc->args); is_pair(y); y = cdr(y)) { + if (!is_pair(car(y))) { + Error_0(sc,"unable to handle non pair element"); + } + if (x == caar(y)) + break; + } + if (is_pair(y)) { + s_return(sc,car(y)); + } else { + s_return(sc,sc->F); + } + + + case OP_GET_CLOSURE: /* get-closure-code */ /* a.k */ + sc->args = car(sc->args); + if (sc->args == sc->NIL) { + s_return(sc,sc->F); + } else if (is_closure(sc->args)) { + s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value))); + } else if (is_macro(sc->args)) { + s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value))); + } else { + s_return(sc,sc->F); + } + case OP_CLOSUREP: /* closure? */ + /* + * Note, macro object is also a closure. + * Therefore, (closure? <#MACRO>) ==> #t + */ + s_retbool(is_closure(car(sc->args))); + case OP_MACROP: /* macro? */ + s_retbool(is_macro(car(sc->args))); + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; /* NOTREACHED */ +} + +typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes); + +typedef int (*test_predicate)(pointer); +static int is_any(pointer p) { return 1;} + +static int is_nonneg(pointer p) { + return ivalue(p)>=0 && is_integer(p); +} + +/* Correspond carefully with following defines! */ +static struct { + test_predicate fct; + const char *kind; +} tests[]={ + {0,0}, /* unused */ + {is_any, 0}, + {is_string, "string"}, + {is_symbol, "symbol"}, + {is_port, "port"}, + {is_inport,"input port"}, + {is_outport,"output port"}, + {is_environment, "environment"}, + {is_pair, "pair"}, + {0, "pair or '()"}, + {is_character, "character"}, + {is_vector, "vector"}, + {is_number, "number"}, + {is_integer, "integer"}, + {is_nonneg, "non-negative integer"} +}; + +#define TST_NONE 0 +#define TST_ANY "\001" +#define TST_STRING "\002" +#define TST_SYMBOL "\003" +#define TST_PORT "\004" +#define TST_INPORT "\005" +#define TST_OUTPORT "\006" +#define TST_ENVIRONMENT "\007" +#define TST_PAIR "\010" +#define TST_LIST "\011" +#define TST_CHAR "\012" +#define TST_VECTOR "\013" +#define TST_NUMBER "\014" +#define TST_INTEGER "\015" +#define TST_NATURAL "\016" + +typedef struct { + dispatch_func func; + char *name; + int min_arity; + int max_arity; + char *arg_tests_encoding; +} op_code_info; + +#define INF_ARG 0xffff + +static op_code_info dispatch_table[]= { +#define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E}, +#include "opdefines.h" + { 0 } +}; + +static const char *procname(pointer x) { + int n=procnum(x); + const char *name=dispatch_table[n].name; + if(name==0) { + name="ILLEGAL!"; + } + return name; +} + +/* kernel of this interpreter */ +static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) { + sc->op = op; + for (;;) { + op_code_info *pcd=dispatch_table+sc->op; + if (pcd->name!=0) { /* if built-in function, check arguments */ + char msg[STRBUFFSIZE]; + int ok=1; + int n=list_length(sc,sc->args); + + /* Check number of arguments */ + if(n<pcd->min_arity) { + ok=0; + snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)", + pcd->name, + pcd->min_arity==pcd->max_arity?"":" at least", + pcd->min_arity); + } + if(ok && n>pcd->max_arity) { + ok=0; + snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)", + pcd->name, + pcd->min_arity==pcd->max_arity?"":" at most", + pcd->max_arity); + } + if(ok) { + if(pcd->arg_tests_encoding!=0) { + int i=0; + int j; + const char *t=pcd->arg_tests_encoding; + pointer arglist=sc->args; + do { + pointer arg=car(arglist); + j=(int)t[0]; + if(j==TST_LIST[0]) { + if(arg!=sc->NIL && !is_pair(arg)) break; + } else { + if(!tests[j].fct(arg)) break; + } + + if(t[1]!=0) {/* last test is replicated as necessary */ + t++; + } + arglist=cdr(arglist); + i++; + } while(i<n); + if(i<n) { + ok=0; + snprintf(msg, STRBUFFSIZE, "%s: argument %d must be: %s", + pcd->name, + i+1, + tests[j].kind); + } + } + } + if(!ok) { + if(_Error_1(sc,msg,0)==sc->NIL) { + return; + } + pcd=dispatch_table+sc->op; + } + } + ok_to_freely_gc(sc); + if (pcd->func(sc, (enum scheme_opcodes)sc->op) == sc->NIL) { + return; + } + if(sc->no_memory) { + fprintf(stderr,"No memory!\n"); + return; + } + } +} + +/* ========== Initialization of internal keywords ========== */ + +static void assign_syntax(scheme *sc, char *name) { + pointer x; + + x = oblist_add_by_name(sc, name); + typeflag(x) |= T_SYNTAX; +} + +static void assign_proc(scheme *sc, enum scheme_opcodes op, char *name) { + pointer x, y; + + x = mk_symbol(sc, name); + y = mk_proc(sc,op); + new_slot_in_env(sc, x, y); +} + +static pointer mk_proc(scheme *sc, enum scheme_opcodes op) { + pointer y; + + y = get_cell(sc, sc->NIL, sc->NIL); + typeflag(y) = (T_PROC | T_ATOM); + ivalue_unchecked(y) = (long) op; + set_num_integer(y); + return y; +} + +/* Hard-coded for the given keywords. Remember to rewrite if more are added! */ +static int syntaxnum(pointer p) { + const char *s=strvalue(car(p)); + switch(strlength(car(p))) { + case 2: + if(s[0]=='i') return OP_IF0; /* if */ + else return OP_OR0; /* or */ + case 3: + if(s[0]=='a') return OP_AND0; /* and */ + else return OP_LET0; /* let */ + case 4: + switch(s[3]) { + case 'e': return OP_CASE0; /* case */ + case 'd': return OP_COND0; /* cond */ + case '*': return OP_LET0AST; /* let* */ + default: return OP_SET0; /* set! */ + } + case 5: + switch(s[2]) { + case 'g': return OP_BEGIN; /* begin */ + case 'l': return OP_DELAY; /* delay */ + case 'c': return OP_MACRO0; /* macro */ + default: return OP_QUOTE; /* quote */ + } + case 6: + switch(s[2]) { + case 'm': return OP_LAMBDA; /* lambda */ + case 'f': return OP_DEF0; /* define */ + default: return OP_LET0REC; /* letrec */ + } + default: + return OP_C0STREAM; /* cons-stream */ + } +} + +/* initialization of TinyScheme */ +#if USE_INTERFACE +INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) { + return cons(sc,a,b); +} +INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) { + return immutable_cons(sc,a,b); +} + +static struct scheme_interface vtbl ={ + scheme_define, + s_cons, + s_immutable_cons, + reserve_cells, + mk_integer, + mk_real, + mk_symbol, + gensym, + mk_string, + mk_counted_string, + mk_character, + mk_vector, + mk_foreign_func, + mk_closure, + putstr, + putcharacter, + + is_string, + string_length, + string_value, + is_number, + nvalue, + ivalue, + rvalue, + is_integer, + is_real, + is_character, + charvalue, + is_list, + is_vector, + list_length, + ivalue, + fill_vector, + vector_elem, + set_vector_elem, + is_port, + is_pair, + pair_car, + pair_cdr, + set_car, + set_cdr, + + is_symbol, + symname, + + is_syntax, + is_proc, + is_foreign, + syntaxname, + is_closure, + is_macro, + closure_code, + closure_env, + + is_continuation, + is_promise, + is_environment, + is_immutable, + setimmutable, + + scheme_load_file, + scheme_load_string +}; +#endif + +scheme *scheme_init_new(void) { + scheme *sc=(scheme*)malloc(sizeof(scheme)); + if(!scheme_init(sc)) { + free(sc); + return 0; + } else { + return sc; + } +} + +scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) { + scheme *sc=(scheme*)malloc(sizeof(scheme)); + if(!scheme_init_custom_alloc(sc,malloc,free)) { + free(sc); + return 0; + } else { + return sc; + } +} + + +int scheme_init(scheme *sc) { + return scheme_init_custom_alloc(sc,malloc,free); +} + +int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) { + int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]); + pointer x; + + num_zero.is_fixnum=1; + num_zero.value.ivalue=0; + num_one.is_fixnum=1; + num_one.value.ivalue=1; + +#if USE_INTERFACE + sc->vptr=&vtbl; +#endif + sc->gensym_cnt=0; + sc->malloc=malloc; + sc->free=free; + sc->last_cell_seg = -1; + sc->sink = &sc->_sink; + sc->NIL = &sc->_NIL; + sc->T = &sc->_HASHT; + sc->F = &sc->_HASHF; + sc->EOF_OBJ=&sc->_EOF_OBJ; + sc->free_cell = &sc->_NIL; + sc->fcells = 0; + sc->no_memory=0; + sc->inport=sc->NIL; + sc->outport=sc->NIL; + sc->save_inport=sc->NIL; + sc->loadport=sc->NIL; + sc->nesting=0; + sc->interactive_repl=0; + sc->print_output=0; + + if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) { + sc->no_memory=1; + return 0; + } + sc->gc_verbose = 0; + dump_stack_initialize(sc); + sc->code = sc->NIL; + sc->tracing=0; + sc->bc_flag = 0; + + /* init sc->NIL */ + typeflag(sc->NIL) = (T_ATOM | MARK); + car(sc->NIL) = cdr(sc->NIL) = sc->NIL; + /* init T */ + typeflag(sc->T) = (T_ATOM | MARK); + car(sc->T) = cdr(sc->T) = sc->T; + /* init F */ + typeflag(sc->F) = (T_ATOM | MARK); + car(sc->F) = cdr(sc->F) = sc->F; + /* init sink */ + typeflag(sc->sink) = (T_PAIR | MARK); + car(sc->sink) = sc->NIL; + /* init c_nest */ + sc->c_nest = sc->NIL; + + sc->oblist = oblist_initial_value(sc); + /* init global_env */ + new_frame_in_env(sc, sc->NIL); + sc->global_env = sc->envir; + /* init else */ + x = mk_symbol(sc,"else"); + new_slot_in_env(sc, x, sc->T); + + assign_syntax(sc, "lambda"); + assign_syntax(sc, "quote"); + assign_syntax(sc, "define"); + assign_syntax(sc, "if"); + assign_syntax(sc, "begin"); + assign_syntax(sc, "set!"); + assign_syntax(sc, "let"); + assign_syntax(sc, "let*"); + assign_syntax(sc, "letrec"); + assign_syntax(sc, "cond"); + assign_syntax(sc, "delay"); + assign_syntax(sc, "and"); + assign_syntax(sc, "or"); + assign_syntax(sc, "cons-stream"); + assign_syntax(sc, "macro"); + assign_syntax(sc, "case"); + + for(i=0; i<n; i++) { + if(dispatch_table[i].name!=0) { + assign_proc(sc, (enum scheme_opcodes)i, dispatch_table[i].name); + } + } + + /* initialization of global pointers to special symbols */ + sc->LAMBDA = mk_symbol(sc, "lambda"); + sc->QUOTE = mk_symbol(sc, "quote"); + sc->QQUOTE = mk_symbol(sc, "quasiquote"); + sc->UNQUOTE = mk_symbol(sc, "unquote"); + sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing"); + sc->FEED_TO = mk_symbol(sc, "=>"); + sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*"); + sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*"); + sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*"); + sc->COMPILE_HOOK = mk_symbol(sc, "*compile-hook*"); + + return !sc->no_memory; +} + +SCHEME_EXPORT void scheme_set_input_port_file(scheme *sc, FILE *fin) { + sc->inport=port_from_file(sc,fin,port_input); +} + +void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) { + sc->inport=port_from_string(sc,start,past_the_end,port_input); +} + +SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fout) { + sc->outport=port_from_file(sc,fout,port_output); +} + +void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) { + sc->outport=port_from_string(sc,start,past_the_end,port_output); +} + +void scheme_set_external_data(scheme *sc, void *p) { + sc->ext_data=p; +} + +void scheme_deinit(scheme *sc) { + int i; + +#if SHOW_ERROR_LINE + char *fname; +#endif + + sc->oblist=sc->NIL; + sc->global_env=sc->NIL; + dump_stack_free(sc); + sc->envir=sc->NIL; + sc->code=sc->NIL; + sc->args=sc->NIL; + sc->value=sc->NIL; + if(is_port(sc->inport)) { + typeflag(sc->inport) = T_ATOM; + } + sc->inport=sc->NIL; + sc->outport=sc->NIL; + if(is_port(sc->save_inport)) { + typeflag(sc->save_inport) = T_ATOM; + } + sc->save_inport=sc->NIL; + if(is_port(sc->loadport)) { + typeflag(sc->loadport) = T_ATOM; + } + sc->loadport=sc->NIL; + sc->gc_verbose=0; + gc(sc,sc->NIL,sc->NIL); + + for(i=0; i<=sc->last_cell_seg; i++) { + sc->free(sc->alloc_seg[i]); + } + +#if SHOW_ERROR_LINE + for(i=0; i<sc->file_i; i++) { + if (sc->load_stack[sc->file_i].kind & port_file) { + fname = sc->load_stack[i].rep.stdio.filename; + if(fname) + sc->free(fname); + } + } +#endif +} + +void scheme_load_file(scheme *sc, FILE *fin) +{ scheme_load_named_file(sc,fin,0); } + +void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename) { + dump_stack_reset(sc); + sc->envir = sc->global_env; + sc->file_i=0; + sc->load_stack[0].kind=port_input|port_file; + sc->load_stack[0].rep.stdio.file=fin; + sc->loadport=mk_port(sc,sc->load_stack); + sc->retcode=0; + if(fin==stdin) { + sc->interactive_repl=1; + } + +#if SHOW_ERROR_LINE + sc->load_stack[0].rep.stdio.curr_line = 0; + if(fin!=stdin && filename) + sc->load_stack[0].rep.stdio.filename = store_string(sc, strlen(filename), filename, 0); + else + sc->load_stack[0].rep.stdio.filename = NULL; +#endif + + sc->inport=sc->loadport; + sc->args = mk_integer(sc,sc->file_i); + Eval_Cycle(sc, OP_T0LVL); + typeflag(sc->loadport)=T_ATOM; + if(sc->retcode==0) { + sc->retcode=sc->nesting!=0; + } +} + +void scheme_load_string(scheme *sc, const char *cmd) { + dump_stack_reset(sc); + sc->envir = sc->global_env; + sc->file_i=0; + sc->load_stack[0].kind=port_input|port_string; + sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */ + sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd); + sc->load_stack[0].rep.string.curr=(char*)cmd; + sc->loadport=mk_port(sc,sc->load_stack); + sc->retcode=0; + sc->interactive_repl=0; + sc->inport=sc->loadport; + sc->args = mk_integer(sc,sc->file_i); + Eval_Cycle(sc, OP_T0LVL); + typeflag(sc->loadport)=T_ATOM; + if(sc->retcode==0) { + sc->retcode=sc->nesting!=0; + } +} + +void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) { + pointer x; + + x=find_slot_in_env(sc,envir,symbol,0); + if (x != sc->NIL) { + set_slot_in_env(sc, x, value); + } else { + new_slot_spec_in_env(sc, envir, symbol, value); + } +} + +#if !STANDALONE +void scheme_register_foreign_func(scheme * sc, scheme_registerable * sr) +{ + scheme_define(sc, + sc->global_env, + mk_symbol(sc,sr->name), + mk_foreign_func(sc, sr->f)); +} + +void scheme_register_foreign_func_list(scheme * sc, + scheme_registerable * list, + int count) +{ + int i; + for(i = 0; i < count; i++) + { + scheme_register_foreign_func(sc, list + i); + } +} + +pointer scheme_apply0(scheme *sc, const char *procname) +{ return scheme_eval(sc, cons(sc,mk_symbol(sc,procname),sc->NIL)); } + +static void save_from_C_call(scheme *sc) +{ + pointer saved_data = + cons(sc, + car(sc->sink), + cons(sc, + sc->envir, + sc->dump)); + /* Push */ + sc->c_nest = cons(sc, saved_data, sc->c_nest); + /* Truncate the dump stack so TS will return here when done, not + directly resume pre-C-call operations. */ + dump_stack_reset(sc); +} + +static void restore_from_C_call(scheme *sc) +{ + car(sc->sink) = caar(sc->c_nest); + sc->envir = cadar(sc->c_nest); + sc->dump = cdr(cdar(sc->c_nest)); + /* Pop */ + sc->c_nest = cdr(sc->c_nest); +} + +/* "func" and "args" are assumed to be already eval'ed. */ +pointer scheme_call(scheme *sc, pointer func, pointer args) +{ + int old_repl = sc->interactive_repl; + sc->interactive_repl = 0; + save_from_C_call(sc); + sc->envir = sc->global_env; + sc->args = args; + sc->code = func; + sc->retcode = 0; + Eval_Cycle(sc, OP_APPLY); + sc->interactive_repl = old_repl; + restore_from_C_call(sc); + return sc->value; +} + +pointer scheme_eval(scheme *sc, pointer obj) +{ + int old_repl = sc->interactive_repl; + sc->interactive_repl = 0; + save_from_C_call(sc); + sc->args = sc->NIL; + sc->code = obj; + sc->retcode = 0; + Eval_Cycle(sc, OP_EVAL); + sc->interactive_repl = old_repl; + restore_from_C_call(sc); + return sc->value; +} + + +#endif + +/* ========== Main ========== */ + +#if STANDALONE + +#if defined(__APPLE__) && !defined (OSX) +int main(int argc, char **argv) +{ + extern MacTS_main(int argc, char **argv); + char** argv; + int argc = ccommand(&argv); + MacTS_main(argc,argv); + return 0; +} +int MacTS_main(int argc, char **argv) { +#else +int main(int argc, char **argv) { +#endif + scheme sc; + FILE *fin; + char *file_name=InitFile; + int retcode; + int isfile=1; + + if(argc==1) { + printf(banner); + } + if(argc==2 && strcmp(argv[1],"-?")==0) { + printf("Usage: tinyscheme -?\n"); + printf("or: tinyscheme [<file1> <file2> ...]\n"); + printf("followed by\n"); + printf(" -1 <file> [<arg1> <arg2> ...]\n"); + printf(" -c <Scheme commands> [<arg1> <arg2> ...]\n"); + printf("assuming that the executable is named tinyscheme.\n"); + printf("Use - as filename for stdin.\n"); + return 1; + } + if(!scheme_init(&sc)) { + fprintf(stderr,"Could not initialize!\n"); + return 2; + } + scheme_set_input_port_file(&sc, stdin); + scheme_set_output_port_file(&sc, stdout); +#if USE_DL + scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext)); +#endif + argv++; + if(g_access(file_name,0)!=0) { + char *p=getenv("TINYSCHEMEINIT"); + if(p!=0) { + file_name=p; + } + } + do { + if(strcmp(file_name,"-")==0) { + fin=stdin; + } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) { + pointer args=sc.NIL; + isfile=file_name[1]=='1'; + file_name=*argv++; + if(strcmp(file_name,"-")==0) { + fin=stdin; + } else if(isfile) { + fin=g_fopen(file_name,"r"); + } + for(;*argv;argv++) { + pointer value=mk_string(&sc,*argv); + args=cons(&sc,value,args); + } + args=reverse_in_place(&sc,sc.NIL,args); + scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args); + + } else { + fin=g_fopen(file_name,"r"); + } + if(isfile && fin==0) { + fprintf(stderr,"Could not open file %s\n",file_name); + } else { + if(isfile) { + scheme_load_named_file(&sc,fin,file_name); + } else { + scheme_load_string(&sc,file_name); + } + if(!isfile || fin!=stdin) { + if(sc.retcode!=0) { + fprintf(stderr,"Errors encountered reading %s\n",file_name); + } + if(isfile) { + fclose(fin); + } + } + } + file_name=*argv++; + } while(file_name!=0); + if(argc==1) { + scheme_load_named_file(&sc,stdin,0); + } + retcode=sc.retcode; + scheme_deinit(&sc); + + return retcode; +} + +#endif + +/* +Local variables: +c-file-style: "k&r" +End: +*/ diff --git a/plug-ins/script-fu/tinyscheme/scheme.h b/plug-ins/script-fu/tinyscheme/scheme.h new file mode 100644 index 0000000..198182c --- /dev/null +++ b/plug-ins/script-fu/tinyscheme/scheme.h @@ -0,0 +1,273 @@ +/* SCHEME.H */ + +#ifndef _SCHEME_H +#define _SCHEME_H + +#include <stdio.h> +#include <glib.h> +#include <glib/gstdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default values for #define'd symbols + */ +#ifndef STANDALONE /* If used as standalone interpreter */ +# define STANDALONE 1 +#endif + +#ifndef _MSC_VER +# ifndef USE_STRLWR +# define USE_STRLWR 1 +# endif +# define SCHEME_EXPORT extern +#else +# define USE_STRLWR 0 +# ifdef _SCHEME_SOURCE +# define SCHEME_EXPORT __declspec(dllexport) +# else +# define SCHEME_EXPORT __declspec(dllimport) +# endif +#endif + +#if USE_NO_FEATURES +# define USE_MATH 0 +# define USE_CHAR_CLASSIFIERS 0 +# define USE_ASCII_NAMES 0 +# define USE_STRING_PORTS 0 +# define USE_ERROR_HOOK 0 +# define USE_TRACING 0 +# define USE_COLON_HOOK 0 +# define USE_DL 0 +# define USE_PLIST 0 +#endif + +/* + * Leave it defined if you want continuations, and also for the Sharp Zaurus. + * Undefine it if you only care about faster speed and not strict Scheme compatibility. + */ +#define USE_SCHEME_STACK + +#if USE_DL +# define USE_INTERFACE 1 +#endif + + +#ifndef USE_MATH /* If math support is needed */ +# define USE_MATH 1 +#endif + +#ifndef USE_CHAR_CLASSIFIERS /* If char classifiers are needed */ +# define USE_CHAR_CLASSIFIERS 1 +#endif + +#ifndef USE_ASCII_NAMES /* If extended escaped characters are needed */ +# define USE_ASCII_NAMES 1 +#endif + +#ifndef USE_STRING_PORTS /* Enable string ports */ +# define USE_STRING_PORTS 1 +#endif + +#ifndef USE_TRACING +# define USE_TRACING 1 +#endif + +#ifndef USE_PLIST +# define USE_PLIST 0 +#endif + +/* To force system errors through user-defined error handling (see *error-hook*) */ +#ifndef USE_ERROR_HOOK +# define USE_ERROR_HOOK 1 +#endif + +#ifndef USE_COLON_HOOK /* Enable qualified qualifier */ +# define USE_COLON_HOOK 1 +#endif + +#ifndef USE_STRLWR +# define USE_STRLWR 1 +#endif + +#ifndef STDIO_ADDS_CR /* Define if DOS/Windows */ +# define STDIO_ADDS_CR 0 +#endif + +#ifndef INLINE +# define INLINE +#endif + +#ifndef USE_INTERFACE +# define USE_INTERFACE 0 +#endif + +#ifndef SHOW_ERROR_LINE /* Show error line in file */ +# define SHOW_ERROR_LINE 1 +#endif + +typedef struct scheme scheme; +typedef struct cell *pointer; + +typedef void * (*func_alloc)(size_t); +typedef void (*func_dealloc)(void *); + +/* num, for generic arithmetic */ +typedef struct num { + char is_fixnum; + union { + long ivalue; + double rvalue; + } value; +} num; + +#if !STANDALONE + +typedef enum { TS_OUTPUT_NORMAL, TS_OUTPUT_ERROR } TsOutputType; + +typedef void (* ts_output_func) (TsOutputType type, + const char *string, + int len, + gpointer data); + +SCHEME_EXPORT void ts_register_output_func (ts_output_func func, + gpointer user_data); +SCHEME_EXPORT void ts_output_string (TsOutputType type, + const char *string, + int len); +#endif + +SCHEME_EXPORT scheme *scheme_init_new(void); +SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free); +SCHEME_EXPORT int scheme_init(scheme *sc); +SCHEME_EXPORT int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc); +SCHEME_EXPORT void scheme_deinit(scheme *sc); +SCHEME_EXPORT void scheme_set_input_port_file(scheme *sc, FILE *fin); +void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end); +SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fin); +void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end); +SCHEME_EXPORT void scheme_load_file(scheme *sc, FILE *fin); +SCHEME_EXPORT void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename); +SCHEME_EXPORT void scheme_load_string(scheme *sc, const char *cmd); +SCHEME_EXPORT pointer scheme_apply0(scheme *sc, const char *procname); +SCHEME_EXPORT pointer scheme_call(scheme *sc, pointer func, pointer args); +SCHEME_EXPORT pointer scheme_eval(scheme *sc, pointer obj); +void scheme_set_external_data(scheme *sc, void *p); +SCHEME_EXPORT void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value); + +typedef pointer (*foreign_func)(scheme *, pointer); + +pointer _cons(scheme *sc, pointer a, pointer b, int immutable); +pointer mk_integer(scheme *sc, long num); +pointer mk_real(scheme *sc, double num); +pointer mk_symbol(scheme *sc, const char *name); +pointer gensym(scheme *sc); +pointer mk_string(scheme *sc, const char *str); +pointer mk_counted_string(scheme *sc, const char *str, int len); +pointer mk_empty_string(scheme *sc, int len, gunichar fill); +pointer mk_character(scheme *sc, gunichar c); +pointer mk_foreign_func(scheme *sc, foreign_func f); +void putcharacter(scheme *sc, gunichar c); +void putstr(scheme *sc, const char *s); +int list_length(scheme *sc, pointer a); +int eqv(pointer a, pointer b); + +SCHEME_EXPORT pointer foreign_error (scheme *sc, const char *s, pointer a); + +#if USE_INTERFACE +struct scheme_interface { + void (*scheme_define)(scheme *sc, pointer env, pointer symbol, pointer value); + pointer (*cons)(scheme *sc, pointer a, pointer b); + pointer (*immutable_cons)(scheme *sc, pointer a, pointer b); + pointer (*reserve_cells)(scheme *sc, int n); + pointer (*mk_integer)(scheme *sc, long num); + pointer (*mk_real)(scheme *sc, double num); + pointer (*mk_symbol)(scheme *sc, const char *name); + pointer (*gensym)(scheme *sc); + pointer (*mk_string)(scheme *sc, const char *str); + pointer (*mk_counted_string)(scheme *sc, const char *str, int len); + pointer (*mk_character)(scheme *sc, gunichar c); + pointer (*mk_vector)(scheme *sc, int len); + pointer (*mk_foreign_func)(scheme *sc, foreign_func f); + pointer (*mk_closure)(scheme *sc, pointer c, pointer e); + void (*putstr)(scheme *sc, const char *s); + void (*putcharacter)(scheme *sc, gunichar c); + + int (*is_string)(pointer p); + int (*string_length)(pointer p); + char *(*string_value)(pointer p); + int (*is_number)(pointer p); + num (*nvalue)(pointer p); + long (*ivalue)(pointer p); + double (*rvalue)(pointer p); + int (*is_integer)(pointer p); + int (*is_real)(pointer p); + int (*is_character)(pointer p); + gunichar (*charvalue)(pointer p); + int (*is_list)(scheme *sc, pointer p); + int (*is_vector)(pointer p); + int (*list_length)(scheme *sc, pointer p); + long (*vector_length)(pointer vec); + void (*fill_vector)(pointer vec, pointer elem); + pointer (*vector_elem)(pointer vec, int ielem); + pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel); + + int (*is_port)(pointer p); + + int (*is_pair)(pointer p); + pointer (*pair_car)(pointer p); + pointer (*pair_cdr)(pointer p); + pointer (*set_car)(pointer p, pointer q); + pointer (*set_cdr)(pointer p, pointer q); + + int (*is_symbol)(pointer p); + char *(*symname)(pointer p); + + int (*is_syntax)(pointer p); + int (*is_proc)(pointer p); + int (*is_foreign)(pointer p); + char *(*syntaxname)(pointer p); + int (*is_closure)(pointer p); + int (*is_macro)(pointer p); + pointer (*closure_code)(pointer p); + pointer (*closure_env)(pointer p); + + int (*is_continuation)(pointer p); + int (*is_promise)(pointer p); + int (*is_environment)(pointer p); + int (*is_immutable)(pointer p); + void (*setimmutable)(pointer p); + + void (*load_file)(scheme *sc, FILE *fin); + void (*load_string)(scheme *sc, const char *input); +}; +#endif + +#if !STANDALONE +typedef struct scheme_registerable +{ + foreign_func f; + const char * name; +} +scheme_registerable; + +void scheme_register_foreign_func(scheme * sc, scheme_registerable * sr); +void scheme_register_foreign_func_list(scheme * sc, + scheme_registerable * list, + int n); + +#endif /* !STANDALONE */ + +#ifdef __cplusplus +} +#endif + +#endif + +/* +Local variables: +c-file-style: "k&r" +End: +*/ |